Feature:remove useless code of sox

pull/221/head
xufuji456 3 years ago
parent 965805fd3b
commit 1c848cd2ab
  1. 4
      app/src/main/cpp/CMakeLists.txt
  2. 66
      app/src/main/cpp/sox/CMakeLists.txt
  3. 322
      app/src/main/cpp/sox/adpcms.c
  4. 55
      app/src/main/cpp/sox/adpcms.h
  5. 21
      app/src/main/cpp/sox/al-fmt.c
  6. 379
      app/src/main/cpp/sox/alsa.c
  7. 90
      app/src/main/cpp/sox/amr-nb.c
  8. 115
      app/src/main/cpp/sox/amr-wb.c
  9. 335
      app/src/main/cpp/sox/amr.h
  10. 47
      app/src/main/cpp/sox/band.h
  11. 325
      app/src/main/cpp/sox/bend.c
  12. 178
      app/src/main/cpp/sox/biquad.c
  13. 78
      app/src/main/cpp/sox/biquad.h
  14. 416
      app/src/main/cpp/sox/biquads.c
  15. 273
      app/src/main/cpp/sox/bit-rot/CoreAudio/CoreAudio.h
  16. 35
      app/src/main/cpp/sox/caf.c
  17. 351
      app/src/main/cpp/sox/chorus.c
  18. 293
      app/src/main/cpp/sox/compand.c
  19. 229
      app/src/main/cpp/sox/compandt.c
  20. 52
      app/src/main/cpp/sox/compandt.h
  21. 49
      app/src/main/cpp/sox/contrast.c
  22. 418
      app/src/main/cpp/sox/coreaudio.c
  23. 165
      app/src/main/cpp/sox/dcshift.c
  24. 137
      app/src/main/cpp/sox/dft_filter.c
  25. 16
      app/src/main/cpp/sox/dft_filter.h
  26. 436
      app/src/main/cpp/sox/dither.c
  27. 63
      app/src/main/cpp/sox/dither.h
  28. 73
      app/src/main/cpp/sox/divide.c
  29. 97
      app/src/main/cpp/sox/earwax.c
  30. 52
      app/src/main/cpp/sox/effects.h
  31. 21
      app/src/main/cpp/sox/f4-fmt.c
  32. 21
      app/src/main/cpp/sox/f8-fmt.c
  33. 399
      app/src/main/cpp/sox/fade.c
  34. 31
      app/src/main/cpp/sox/fap.c
  35. 105
      app/src/main/cpp/sox/fir.c
  36. 145
      app/src/main/cpp/sox/firfit.c
  37. 606
      app/src/main/cpp/sox/flac.c
  38. 275
      app/src/main/cpp/sox/flanger.c
  39. 40
      app/src/main/cpp/sox/formats.h
  40. 167
      app/src/main/cpp/sox/g721.c
  41. 151
      app/src/main/cpp/sox/g723_24.c
  42. 171
      app/src/main/cpp/sox/g723_40.c
  43. 575
      app/src/main/cpp/sox/g72x.c
  44. 157
      app/src/main/cpp/sox/g72x.h
  45. 276
      app/src/main/cpp/sox/gain.c
  46. 102
      app/src/main/cpp/sox/hilbert.c
  47. 227
      app/src/main/cpp/sox/id3.c
  48. 25
      app/src/main/cpp/sox/id3.h
  49. 33
      app/src/main/cpp/sox/ima-fmt.c
  50. 21
      app/src/main/cpp/sox/la-fmt.c
  51. 492
      app/src/main/cpp/sox/ladspa.c
  52. 603
      app/src/main/cpp/sox/ladspa.h
  53. 129
      app/src/main/cpp/sox/loudness.c
  54. 21
      app/src/main/cpp/sox/lu-fmt.c
  55. 524
      app/src/main/cpp/sox/mcompand.c
  56. 106
      app/src/main/cpp/sox/mcompand_xover.h
  57. 171
      app/src/main/cpp/sox/mp3-util.h
  58. 1299
      app/src/main/cpp/sox/mp3.c
  59. 223
      app/src/main/cpp/sox/noiseprof.c
  60. 357
      app/src/main/cpp/sox/noisered.c
  61. 26
      app/src/main/cpp/sox/noisered.h
  62. 235
      app/src/main/cpp/sox/opus.c
  63. 446
      app/src/main/cpp/sox/oss.c
  64. 71
      app/src/main/cpp/sox/overdrive.c
  65. 180
      app/src/main/cpp/sox/pad.c
  66. 31
      app/src/main/cpp/sox/paf.c
  67. 147
      app/src/main/cpp/sox/phaser.c
  68. 172
      app/src/main/cpp/sox/pulseaudio.c
  69. 30
      app/src/main/cpp/sox/pvf.c
  70. 712
      app/src/main/cpp/sox/rate.c
  71. 187
      app/src/main/cpp/sox/rate_filters.h
  72. 39
      app/src/main/cpp/sox/rate_half_fir.h
  73. 91
      app/src/main/cpp/sox/rate_poly_fir.h
  74. 48
      app/src/main/cpp/sox/rate_poly_fir0.h
  75. 61
      app/src/main/cpp/sox/raw-fmt.c
  76. 284
      app/src/main/cpp/sox/remix.c
  77. 114
      app/src/main/cpp/sox/repeat.c
  78. 86
      app/src/main/cpp/sox/reverse.c
  79. 21
      app/src/main/cpp/sox/s1-fmt.c
  80. 21
      app/src/main/cpp/sox/s2-fmt.c
  81. 21
      app/src/main/cpp/sox/s3-fmt.c
  82. 21
      app/src/main/cpp/sox/s4-fmt.c
  83. 30
      app/src/main/cpp/sox/sd2.c
  84. 690
      app/src/main/cpp/sox/silence.c
  85. 157
      app/src/main/cpp/sox/sinc.c
  86. 141
      app/src/main/cpp/sox/skeleff.c
  87. 532
      app/src/main/cpp/sox/sndfile.c
  88. 246
      app/src/main/cpp/sox/sndio.c
  89. 108
      app/src/main/cpp/sox/sox-fmt.c
  90. 1009
      app/src/main/cpp/sox/spectrogram.c
  91. 349
      app/src/main/cpp/sox/speexdsp.c
  92. 302
      app/src/main/cpp/sox/splice.c
  93. 336
      app/src/main/cpp/sox/stat.c
  94. 298
      app/src/main/cpp/sox/stats.c
  95. 326
      app/src/main/cpp/sox/stretch.c
  96. 520
      app/src/main/cpp/sox/sunaudio.c
  97. 62
      app/src/main/cpp/sox/swap.c
  98. 677
      app/src/main/cpp/sox/synth.c
  99. 47
      app/src/main/cpp/sox/tremolo.c
  100. 216
      app/src/main/cpp/sox/trim.c
  101. Some files were not shown because too many files have changed in this diff Show More

@ -55,8 +55,8 @@ set_target_properties( ffmpeg
../../../../libs/${CMAKE_ANDROID_ARCH_ABI}/libffmpeg.so )
# third-party library: sox
#add_subdirectory(src/main/cpp/sox)
#include_directories(src/main/cpp/sox)
#add_subdirectory(sox)
#include_directories(sox)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=gnu++11")

@ -21,91 +21,25 @@ if (NOT EXTERNAL_GSM)
endif (NOT EXTERNAL_GSM)
set(effects_srcs
bend.c
biquad.c
biquads.c
chorus.c
compand.c
compandt.c
contrast.c
dcshift.c
delay.c
dft_filter.c
dither.c
divide.c
downsample.c
earwax.c
echo.c
echos.c
fade.c
fft4g.c
fir.c
firfit.c
flanger.c
gain.c
hilbert.c
input.c
loudness.c
mcompand.c
noiseprof.c
noisered.c
output.c
overdrive.c
pad.c
phaser.c
rate.c
remix.c
repeat.c
reverb.c
reverse.c
silence.c
sinc.c
skeleff.c
speed.c
splice.c
stat.c
stats.c
stretch.c
swap.c
synth.c
tempo.c
tremolo.c
trim.c
upsample.c
vad.c
vol.c
)
set(formats_srcs
adpcm.c
adpcms.c
al-fmt.c
coreaudio.c
f4-fmt.c
f8-fmt.c
g711.c
g721.c
g723_24.c
g723_40.c
g72x.c
ima-fmt.c
ima_rw.c
la-fmt.c
lu-fmt.c
raw.c
raw-fmt.c
s1-fmt.c
s2-fmt.c
s3-fmt.c
s4-fmt.c
sox-fmt.c
u1-fmt.c
u2-fmt.c
u3-fmt.c
u4-fmt.c
ul-fmt.c
voc.c
vox.c
vox-fmt.c
wav.c
)

@ -1,322 +0,0 @@
/* libSoX ADPCM codecs: IMA, OKI, CL. (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 "adpcms.h"
static int const ima_steps[89] = { /* ~16-bit precision; 4 bit code */
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};
static int const oki_steps[49] = { /* ~12-bit precision; 4 bit code */
256, 272, 304, 336, 368, 400, 448, 496, 544, 592, 656, 720, 800, 880, 960,
1056, 1168, 1280, 1408, 1552, 1712, 1888, 2080, 2288, 2512, 2768, 3040, 3344,
3680, 4048, 4464, 4912, 5392, 5936, 6528, 7184, 7904, 8704, 9568, 10528,
11584, 12736, 14016, 15408, 16960, 18656, 20512, 22576, 24832};
static int const step_changes[8] = {-1, -1, -1, -1, 2, 4, 6, 8};
/* Creative Labs ~8 bit precision; 4, 3, & 2 bit codes: */
static int const cl4_steps[4] = {0x100, 0x200, 0x400, 0x800};
static int const cl4_changes[8] = {-1, 0, 0, 0, 0, 1, 1, 1};
static int const cl3_steps[5] = {0x100, 0x200, 0x400, 0x800, 0xA00};
static int const cl3_changes[4] = {-1, 0, 0, 1};
static int const cl2_steps[6] = {0x100, 0x200, 0x400, 0x800, 0x1000, 0x2000};
static int const cl2_changes[2] = {-1, 1};
static adpcm_setup_t const setup_table[] = {
{88, 8, 2, ima_steps, step_changes, ~0},
{48, 8, 2, oki_steps, step_changes, ~15},
{ 3, 8, 0, cl4_steps, cl4_changes , ~255},
{ 4, 4, 0, cl3_steps, cl3_changes , ~255},
{ 5, 2, 0, cl2_steps, cl2_changes , ~255},
};
void lsx_adpcm_init(adpcm_t * p, int type, int first_sample)
{
p->setup = setup_table[type];
p->last_output = first_sample;
p->step_index = 0;
p->errors = 0;
}
#define min_sample -0x8000
#define max_sample 0x7fff
int lsx_adpcm_decode(int code, adpcm_t * p)
{
int s = ((code & (p->setup.sign - 1)) << 1) | 1;
s = ((p->setup.steps[p->step_index] * s) >> (p->setup.shift + 1)) & p->setup.mask;
if (code & p->setup.sign)
s = -s;
s += p->last_output;
if (s < min_sample || s > max_sample) {
int grace = (p->setup.steps[p->step_index] >> (p->setup.shift + 1)) & p->setup.mask;
if (s < min_sample - grace || s > max_sample + grace) {
lsx_debug_most("code=%i step=%i grace=%i s=%i",
code & (2 * p->setup.sign - 1), p->setup.steps[p->step_index], grace, s);
p->errors++;
}
s = s < min_sample? min_sample : max_sample;
}
p->step_index += p->setup.changes[code & (p->setup.sign - 1)];
p->step_index = range_limit(p->step_index, 0, p->setup.max_step_index);
return p->last_output = s;
}
int lsx_adpcm_encode(int sample, adpcm_t * p)
{
int delta = sample - p->last_output;
int sign = 0;
int code;
if (delta < 0) {
sign = p->setup.sign;
delta = -delta;
}
code = (delta << p->setup.shift) / p->setup.steps[p->step_index];
code = sign | min(code, p->setup.sign - 1);
lsx_adpcm_decode(code, p); /* Update encoder state */
return code;
}
/*
* Format methods
*
* Almost like the raw format functions, but cannot be used directly
* since they require an additional state parameter.
*/
/******************************************************************************
* Function : lsx_adpcm_reset
* Description: Resets the ADPCM codec state.
* Parameters : state - ADPCM state structure
* type - SOX_ENCODING_OKI_ADPCM or SOX_ENCODING_IMA_ADPCM
* Returns :
* Exceptions :
* Notes : 1. This function is used for framed ADPCM formats to reset
* the decoder between frames.
******************************************************************************/
void lsx_adpcm_reset(adpcm_io_t * state, sox_encoding_t type)
{
state->file.count = 0;
state->file.pos = 0;
state->store.byte = 0;
state->store.flag = 0;
lsx_adpcm_init(&state->encoder, (type == SOX_ENCODING_OKI_ADPCM) ? 1 : 0, 0);
}
/******************************************************************************
* Function : lsx_adpcm_start
* Description: Initialises the file parameters and ADPCM codec state.
* Parameters : ft - file info structure
* state - ADPCM state structure
* type - SOX_ENCODING_OKI_ADPCM or SOX_ENCODING_IMA_ADPCM
* Returns : int - SOX_SUCCESS
* SOX_EOF
* Exceptions :
* Notes : 1. This function can be used as a startread or
* startwrite method.
* 2. VOX file format is 4-bit OKI ADPCM that decodes to
* to 12 bit signed linear PCM.
* 3. Dialogic only supports 6kHz, 8kHz and 11 kHz sampling
* rates but the codecs allows any user specified rate.
******************************************************************************/
static int adpcm_start(sox_format_t * ft, adpcm_io_t * state, sox_encoding_t type)
{
/* setup file info */
state->file.buf = lsx_malloc(sox_globals.bufsiz);
state->file.size = sox_globals.bufsiz;
ft->signal.channels = 1;
lsx_adpcm_reset(state, type);
return lsx_rawstart(ft, sox_true, sox_false, sox_true, type, 4);
}
int lsx_adpcm_oki_start(sox_format_t * ft, adpcm_io_t * state)
{
return adpcm_start(ft, state, SOX_ENCODING_OKI_ADPCM);
}
int lsx_adpcm_ima_start(sox_format_t * ft, adpcm_io_t * state)
{
return adpcm_start(ft, state, SOX_ENCODING_IMA_ADPCM);
}
/******************************************************************************
* Function : lsx_adpcm_read
* Description: Converts the OKI ADPCM 4-bit samples to 16-bit signed PCM and
* then scales the samples to full sox_sample_t range.
* Parameters : ft - file info structure
* state - ADPCM state structure
* buffer - output buffer
* len - size of output buffer
* Returns : - number of samples returned in buffer
* Exceptions :
* Notes :
******************************************************************************/
size_t lsx_adpcm_read(sox_format_t * ft, adpcm_io_t * state, sox_sample_t * buffer, size_t len)
{
size_t n = 0;
uint8_t byte;
int16_t word;
if (len && state->store.flag) {
word = lsx_adpcm_decode(state->store.byte, &state->encoder);
*buffer++ = SOX_SIGNED_16BIT_TO_SAMPLE(word, ft->clips);
state->store.flag = 0;
++n;
}
while (n < len && lsx_read_b_buf(ft, &byte, (size_t) 1) == 1) {
word = lsx_adpcm_decode(byte >> 4, &state->encoder);
*buffer++ = SOX_SIGNED_16BIT_TO_SAMPLE(word, ft->clips);
if (++n < len) {
word = lsx_adpcm_decode(byte, &state->encoder);
*buffer++ = SOX_SIGNED_16BIT_TO_SAMPLE(word, ft->clips);
++n;
} else {
state->store.byte = byte;
state->store.flag = 1;
}
}
return n;
}
/******************************************************************************
* Function : stopread
* Description: Frees the internal buffer allocated in voxstart/imastart.
* Parameters : ft - file info structure
* state - ADPCM state structure
* Returns : int - SOX_SUCCESS
* Exceptions :
* Notes :
******************************************************************************/
int lsx_adpcm_stopread(sox_format_t * ft UNUSED, adpcm_io_t * state)
{
if (state->encoder.errors)
lsx_warn("%s: ADPCM state errors: %u", ft->filename, state->encoder.errors);
free(state->file.buf);
return (SOX_SUCCESS);
}
/******************************************************************************
* Function : write
* Description: Converts the supplied buffer to 12 bit linear PCM and encodes
* to OKI ADPCM 4-bit samples (packed a two nibbles per byte).
* Parameters : ft - file info structure
* state - ADPCM state structure
* buffer - output buffer
* length - size of output buffer
* Returns : int - SOX_SUCCESS
* SOX_EOF
* Exceptions :
* Notes :
******************************************************************************/
size_t lsx_adpcm_write(sox_format_t * ft, adpcm_io_t * state, const sox_sample_t * buffer, size_t length)
{
size_t count = 0;
uint8_t byte = state->store.byte;
uint8_t flag = state->store.flag;
short word;
while (count < length) {
SOX_SAMPLE_LOCALS;
word = SOX_SAMPLE_TO_SIGNED_16BIT(*buffer++, ft->clips);
byte <<= 4;
byte |= lsx_adpcm_encode(word, &state->encoder) & 0x0F;
flag = !flag;
if (flag == 0) {
state->file.buf[state->file.count++] = byte;
if (state->file.count >= state->file.size) {
lsx_writebuf(ft, state->file.buf, state->file.count);
state->file.count = 0;
}
}
count++;
}
/* keep last byte across calls */
state->store.byte = byte;
state->store.flag = flag;
return (count);
}
/******************************************************************************
* Function : lsx_adpcm_flush
* Description: Flushes any leftover samples.
* Parameters : ft - file info structure
* state - ADPCM state structure
* Returns :
* Exceptions :
* Notes : 1. Called directly for writing framed formats
******************************************************************************/
void lsx_adpcm_flush(sox_format_t * ft, adpcm_io_t * state)
{
uint8_t byte = state->store.byte;
uint8_t flag = state->store.flag;
/* flush remaining samples */
if (flag != 0) {
byte <<= 4;
state->file.buf[state->file.count++] = byte;
}
if (state->file.count > 0)
lsx_writebuf(ft, state->file.buf, state->file.count);
}
/******************************************************************************
* Function : lsx_adpcm_stopwrite
* Description: Flushes any leftover samples and frees the internal buffer
* allocated in voxstart/imastart.
* Parameters : ft - file info structure
* state - ADPCM state structure
* Returns : int - SOX_SUCCESS
* Exceptions :
* Notes :
******************************************************************************/
int lsx_adpcm_stopwrite(sox_format_t * ft, adpcm_io_t * state)
{
lsx_adpcm_flush(ft, state);
free(state->file.buf);
return (SOX_SUCCESS);
}

@ -1,55 +0,0 @@
/* libSoX ADPCM codecs: IMA, OKI, CL. (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
*/
typedef struct {
int max_step_index;
int sign;
int shift;
int const * steps;
int const * changes;
int mask;
} adpcm_setup_t;
typedef struct {
adpcm_setup_t setup;
int last_output;
int step_index;
int errors;
} adpcm_t;
void lsx_adpcm_init(adpcm_t * p, int type, int first_sample);
int lsx_adpcm_decode(int code, adpcm_t * p);
int lsx_adpcm_encode(int sample, adpcm_t * p);
typedef struct {
adpcm_t encoder;
struct {
uint8_t byte; /* write store */
uint8_t flag;
} store;
sox_fileinfo_t file;
} adpcm_io_t;
/* Format methods */
void lsx_adpcm_reset(adpcm_io_t * state, sox_encoding_t type);
int lsx_adpcm_oki_start(sox_format_t * ft, adpcm_io_t * state);
int lsx_adpcm_ima_start(sox_format_t * ft, adpcm_io_t * state);
size_t lsx_adpcm_read(sox_format_t * ft, adpcm_io_t * state, sox_sample_t *buffer, size_t len);
int lsx_adpcm_stopread(sox_format_t * ft, adpcm_io_t * state);
size_t lsx_adpcm_write(sox_format_t * ft, adpcm_io_t * state, const sox_sample_t *buffer, size_t length);
void lsx_adpcm_flush(sox_format_t * ft, adpcm_io_t * state);
int lsx_adpcm_stopwrite(sox_format_t * ft, adpcm_io_t * state);

@ -1,21 +0,0 @@
/* File format: raw A-law (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
*/
#include "sox_i.h"
#include "raw.h"
RAW_FORMAT(al, 8, 0, ALAW)

@ -1,379 +0,0 @@
/* libSoX device driver: ALSA (c) 2006-2012 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 <alsa/asoundlib.h>
typedef struct {
snd_pcm_uframes_t buf_len, period;
snd_pcm_t * pcm;
char * buf;
unsigned int format;
} priv_t;
static const
struct {
unsigned int bits;
enum _snd_pcm_format alsa_fmt;
unsigned int bytes; /* occupied in the buffer per sample */
sox_encoding_t enc;
} formats[] = {
/* order by # of bits; within that, preferred first */
{ 8, SND_PCM_FORMAT_S8, 1, SOX_ENCODING_SIGN2 },
{ 8, SND_PCM_FORMAT_U8, 1, SOX_ENCODING_UNSIGNED },
{ 16, SND_PCM_FORMAT_S16, 2, SOX_ENCODING_SIGN2 },
{ 16, SND_PCM_FORMAT_U16, 2, SOX_ENCODING_UNSIGNED },
{ 24, SND_PCM_FORMAT_S24, 4, SOX_ENCODING_SIGN2 },
{ 24, SND_PCM_FORMAT_U24, 4, SOX_ENCODING_UNSIGNED },
{ 24, SND_PCM_FORMAT_S24_3LE, 3, SOX_ENCODING_SIGN2 },
{ 32, SND_PCM_FORMAT_S32, 4, SOX_ENCODING_SIGN2 },
{ 32, SND_PCM_FORMAT_U32, 4, SOX_ENCODING_UNSIGNED },
{ 0, 0, 0, SOX_ENCODING_UNKNOWN } /* end of list */
};
static int select_format(
sox_encoding_t * encoding_,
unsigned * nbits_,
snd_pcm_format_mask_t const * mask,
unsigned int * format)
{
unsigned int from = 0, to; /* NB: "to" actually points one after the last */
int cand = -1;
while (formats[from].bits < *nbits_ && formats[from].bits != 0)
from++; /* find the first entry with at least *nbits_ bits */
for (to = from; formats[to].bits != 0; to++) ; /* find end of list */
while (to > 0) {
unsigned int i, bits_next = 0;
for (i = from; i < to; i++) {
lsx_debug_most("select_format: trying #%u", i);
if (snd_pcm_format_mask_test(mask, formats[i].alsa_fmt)) {
if (formats[i].enc == *encoding_) {
cand = i;
break; /* found a match */
} else if (cand == -1) /* don't overwrite a candidate that
was earlier in the list */
cand = i; /* will work, but encoding differs */
}
}
if (cand != -1)
break;
/* no candidate found yet; now try formats with less bits: */
to = from;
if (from > 0)
bits_next = formats[from-1].bits;
while (from && formats[from-1].bits == bits_next)
from--; /* go back to the first entry with bits_next bits */
}
if (cand == -1) {
lsx_debug("select_format: no suitable ALSA format found");
return -1;
}
if (*nbits_ != formats[cand].bits || *encoding_ != formats[cand].enc) {
lsx_warn("can't encode %u-bit %s", *nbits_,
sox_encodings_info[*encoding_].desc);
*nbits_ = formats[cand].bits;
*encoding_ = formats[cand].enc;
}
lsx_debug("selecting format %d: %s (%s)", cand,
snd_pcm_format_name(formats[cand].alsa_fmt),
snd_pcm_format_description(formats[cand].alsa_fmt));
*format = cand;
return 0;
}
#define _(x,y) do {if ((err = x y) < 0) {lsx_fail_errno(ft, SOX_EPERM, #x " error: %s", snd_strerror(err)); goto error;} } while (0)
static int setup(sox_format_t * ft)
{
priv_t * p = (priv_t *)ft->priv;
snd_pcm_hw_params_t * params = NULL;
snd_pcm_format_mask_t * mask = NULL;
snd_pcm_uframes_t min, max;
unsigned n;
int err;
_(snd_pcm_open, (&p->pcm, ft->filename, ft->mode == 'r'? SND_PCM_STREAM_CAPTURE : SND_PCM_STREAM_PLAYBACK, 0));
_(snd_pcm_hw_params_malloc, (&params));
_(snd_pcm_hw_params_any, (p->pcm, params));
#if SND_LIB_VERSION >= 0x010009 /* Disable alsa-lib resampling: */
_(snd_pcm_hw_params_set_rate_resample, (p->pcm, params, 0));
#endif
_(snd_pcm_hw_params_set_access, (p->pcm, params, SND_PCM_ACCESS_RW_INTERLEAVED));
_(snd_pcm_format_mask_malloc, (&mask)); /* Set format: */
snd_pcm_hw_params_get_format_mask(params, mask);
_(select_format, (&ft->encoding.encoding, &ft->encoding.bits_per_sample, mask, &p->format));
_(snd_pcm_hw_params_set_format, (p->pcm, params, formats[p->format].alsa_fmt));
snd_pcm_format_mask_free(mask), mask = NULL;
n = ft->signal.rate; /* Set rate: */
_(snd_pcm_hw_params_set_rate_near, (p->pcm, params, &n, 0));
ft->signal.rate = n;
n = ft->signal.channels; /* Set channels: */
_(snd_pcm_hw_params_set_channels_near, (p->pcm, params, &n));
ft->signal.channels = n;
/* Get number of significant bits: */
if ((err = snd_pcm_hw_params_get_sbits(params)) > 0)
ft->signal.precision = min(err, SOX_SAMPLE_PRECISION);
else lsx_debug("snd_pcm_hw_params_get_sbits can't tell precision: %s",
snd_strerror(err));
/* Set buf_len > > sox_globals.bufsiz for no underrun: */
p->buf_len = sox_globals.bufsiz * 8 / formats[p->format].bytes /
ft->signal.channels;
_(snd_pcm_hw_params_get_buffer_size_min, (params, &min));
_(snd_pcm_hw_params_get_buffer_size_max, (params, &max));
p->period = range_limit(p->buf_len, min, max) / 8;
p->buf_len = p->period * 8;
_(snd_pcm_hw_params_set_period_size_near, (p->pcm, params, &p->period, 0));
_(snd_pcm_hw_params_set_buffer_size_near, (p->pcm, params, &p->buf_len));
if (p->period * 2 > p->buf_len) {
lsx_fail_errno(ft, SOX_EPERM, "buffer too small");
goto error;
}
_(snd_pcm_hw_params, (p->pcm, params)); /* Configure ALSA */
snd_pcm_hw_params_free(params), params = NULL;
_(snd_pcm_prepare, (p->pcm));
p->buf_len *= ft->signal.channels; /* No longer in `frames' */
p->buf = lsx_malloc(p->buf_len * formats[p->format].bytes);
return SOX_SUCCESS;
error:
if (mask) snd_pcm_format_mask_free(mask);
if (params) snd_pcm_hw_params_free(params);
return SOX_EOF;
}
static int recover(sox_format_t * ft, snd_pcm_t * pcm, int err)
{
if (err == -EPIPE)
lsx_warn("%s-run", ft->mode == 'r'? "over" : "under");
else if (err != -ESTRPIPE)
lsx_warn("%s", snd_strerror(err));
else while ((err = snd_pcm_resume(pcm)) == -EAGAIN) {
lsx_report("suspended");
sleep(1); /* Wait until the suspend flag is released */
}
if (err < 0 && (err = snd_pcm_prepare(pcm)) < 0)
lsx_fail_errno(ft, SOX_EPERM, "%s", snd_strerror(err));
return err;
}
static size_t read_(sox_format_t * ft, sox_sample_t * buf, size_t len)
{
priv_t * p = (priv_t *)ft->priv;
snd_pcm_sframes_t i, n;
size_t done;
len = min(len, p->buf_len);
for (done = 0; done < len; done += n) {
do {
n = snd_pcm_readi(p->pcm, p->buf, (len - done) / ft->signal.channels);
if (n < 0 && recover(ft, p->pcm, (int)n) < 0)
return 0;
} while (n <= 0);
i = n *= ft->signal.channels;
switch (formats[p->format].alsa_fmt) {
case SND_PCM_FORMAT_S8: {
int8_t * buf1 = (int8_t *)p->buf;
while (i--) *buf++ = SOX_SIGNED_8BIT_TO_SAMPLE(*buf1++,);
break;
}
case SND_PCM_FORMAT_U8: {
uint8_t * buf1 = (uint8_t *)p->buf;
while (i--) *buf++ = SOX_UNSIGNED_8BIT_TO_SAMPLE(*buf1++,);
break;
}
case SND_PCM_FORMAT_S16: {
int16_t * buf1 = (int16_t *)p->buf;
if (ft->encoding.reverse_bytes) while (i--)
*buf++ = SOX_SIGNED_16BIT_TO_SAMPLE(lsx_swapw(*buf1++),);
else
while (i--) *buf++ = SOX_SIGNED_16BIT_TO_SAMPLE(*buf1++,);
break;
}
case SND_PCM_FORMAT_U16: {
uint16_t * buf1 = (uint16_t *)p->buf;
if (ft->encoding.reverse_bytes) while (i--)
*buf++ = SOX_UNSIGNED_16BIT_TO_SAMPLE(lsx_swapw(*buf1++),);
else
while (i--) *buf++ = SOX_UNSIGNED_16BIT_TO_SAMPLE(*buf1++,);
break;
}
case SND_PCM_FORMAT_S24: {
sox_int24_t * buf1 = (sox_int24_t *)p->buf;
while (i--) *buf++ = SOX_SIGNED_24BIT_TO_SAMPLE(*buf1++,);
break;
}
case SND_PCM_FORMAT_S24_3LE: {
unsigned char *buf1 = (unsigned char *)p->buf;
while (i--) {
uint32_t temp;
temp = *buf1++;
temp |= *buf1++ << 8;
temp |= *buf1++ << 16;
*buf++ = SOX_SIGNED_24BIT_TO_SAMPLE((sox_int24_t)temp,);
}
break;
}
case SND_PCM_FORMAT_U24: {
sox_uint24_t * buf1 = (sox_uint24_t *)p->buf;
while (i--) *buf++ = SOX_UNSIGNED_24BIT_TO_SAMPLE(*buf1++,);
break;
}
case SND_PCM_FORMAT_S32: {
int32_t * buf1 = (int32_t *)p->buf;
while (i--) *buf++ = SOX_SIGNED_32BIT_TO_SAMPLE(*buf1++,);
break;
}
case SND_PCM_FORMAT_U32: {
uint32_t * buf1 = (uint32_t *)p->buf;
while (i--) *buf++ = SOX_UNSIGNED_32BIT_TO_SAMPLE(*buf1++,);
break;
}
default: lsx_fail_errno(ft, SOX_EFMT, "invalid format");
return 0;
}
}
return len;
}
static size_t write_(sox_format_t * ft, sox_sample_t const * buf, size_t len)
{
priv_t * p = (priv_t *)ft->priv;
size_t done, i, n;
snd_pcm_sframes_t actual;
SOX_SAMPLE_LOCALS;
for (done = 0; done < len; done += n) {
i = n = min(len - done, p->buf_len);
switch (formats[p->format].alsa_fmt) {
case SND_PCM_FORMAT_S8: {
int8_t * buf1 = (int8_t *)p->buf;
while (i--) *buf1++ = SOX_SAMPLE_TO_SIGNED_8BIT(*buf++, ft->clips);
break;
}
case SND_PCM_FORMAT_U8: {
uint8_t * buf1 = (uint8_t *)p->buf;
while (i--) *buf1++ = SOX_SAMPLE_TO_UNSIGNED_8BIT(*buf++, ft->clips);
break;
}
case SND_PCM_FORMAT_S16: {
int16_t * buf1 = (int16_t *)p->buf;
if (ft->encoding.reverse_bytes) while (i--)
*buf1++ = lsx_swapw(SOX_SAMPLE_TO_SIGNED_16BIT(*buf++, ft->clips));
else
while (i--) *buf1++ = SOX_SAMPLE_TO_SIGNED_16BIT(*buf++, ft->clips);
break;
}
case SND_PCM_FORMAT_U16: {
uint16_t * buf1 = (uint16_t *)p->buf;
if (ft->encoding.reverse_bytes) while (i--)
*buf1++ = lsx_swapw(SOX_SAMPLE_TO_UNSIGNED_16BIT(*buf++, ft->clips));
else
while (i--) *buf1++ = SOX_SAMPLE_TO_UNSIGNED_16BIT(*buf++, ft->clips);
break;
}
case SND_PCM_FORMAT_S24: {
sox_int24_t * buf1 = (sox_int24_t *)p->buf;
while (i--) *buf1++ = SOX_SAMPLE_TO_SIGNED_24BIT(*buf++, ft->clips);
break;
}
case SND_PCM_FORMAT_S24_3LE: {
unsigned char *buf1 = (unsigned char *)p->buf;
while (i--) {
uint32_t temp = (uint32_t)SOX_SAMPLE_TO_SIGNED_24BIT(*buf++, ft->clips);
*buf1++ = (temp & 0x000000FF);
*buf1++ = (temp & 0x0000FF00) >> 8;
*buf1++ = (temp & 0x00FF0000) >> 16;
}
break;
}
case SND_PCM_FORMAT_U24: {
sox_uint24_t * buf1 = (sox_uint24_t *)p->buf;
while (i--) *buf1++ = SOX_SAMPLE_TO_UNSIGNED_24BIT(*buf++, ft->clips);
break;
}
case SND_PCM_FORMAT_S32: {
int32_t * buf1 = (int32_t *)p->buf;
while (i--) *buf1++ = SOX_SAMPLE_TO_SIGNED_32BIT(*buf++, ft->clips);
break;
}
case SND_PCM_FORMAT_U32: {
uint32_t * buf1 = (uint32_t *)p->buf;
while (i--) *buf1++ = SOX_SAMPLE_TO_UNSIGNED_32BIT(*buf++, ft->clips);
break;
}
default: lsx_fail_errno(ft, SOX_EFMT, "invalid format");
return 0;
}
for (i = 0; i < n; i += actual * ft->signal.channels) do {
actual = snd_pcm_writei(p->pcm,
p->buf + i * formats[p->format].bytes,
(n - i) / ft->signal.channels);
if (errno == EAGAIN) /* Happens naturally; don't report it: */
errno = 0;
if (actual < 0 && recover(ft, p->pcm, (int)actual) < 0)
return 0;
} while (actual < 0);
}
return len;
}
static int stop(sox_format_t * ft)
{
priv_t * p = (priv_t *)ft->priv;
snd_pcm_close(p->pcm);
free(p->buf);
return SOX_SUCCESS;
}
static int stop_write(sox_format_t * ft)
{
priv_t * p = (priv_t *)ft->priv;
size_t n = ft->signal.channels * p->period, npad = n - (ft->olength % n);
sox_sample_t * buf = lsx_calloc(npad, sizeof(*buf)); /* silent samples */
if (npad != n) /* pad to hardware period: */
write_(ft, buf, npad);
free(buf);
snd_pcm_drain(p->pcm);
return stop(ft);
}
LSX_FORMAT_HANDLER(alsa)
{
static char const * const names[] = {"alsa", NULL};
static unsigned const write_encodings[] = {
SOX_ENCODING_SIGN2 , 32, 24, 16, 8, 0,
SOX_ENCODING_UNSIGNED, 32, 24, 16, 8, 0,
0};
static sox_format_handler_t const handler = {SOX_LIB_VERSION_CODE,
"Advanced Linux Sound Architecture device driver",
names, SOX_FILE_DEVICE | SOX_FILE_NOSTDIO,
setup, read_, stop, setup, write_, stop_write,
NULL, write_encodings, NULL, sizeof(priv_t)
};
return &handler;
}

@ -1,90 +0,0 @@
/* File format: AMR-NB (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
*/
/*
* In order to use the AMR format with SoX, you need to have an
* AMR library installed at SoX build time. The SoX build system
* recognizes the AMR implementations available from
* http://opencore-amr.sourceforge.net/
*/
#include "sox_i.h"
/* Common definitions: */
enum amrnb_mode { amrnb_mode_dummy };
static const unsigned amrnb_block_size[] = {13, 14, 16, 18, 20, 21, 27, 32, 6, 0, 0, 0, 0, 0, 0, 1};
static char const amrnb_magic[] = "#!AMR\n";
#define amr_block_size amrnb_block_size
#define amr_magic amrnb_magic
#define amr_priv_t amrnb_priv_t
#define amr_opencore_funcs amrnb_opencore_funcs
#define amr_gp3_funcs amrnb_gp3_funcs
#define AMR_CODED_MAX 32 /* max coded size */
#define AMR_ENCODING SOX_ENCODING_AMR_NB
#define AMR_FORMAT_FN lsx_amr_nb_format_fn
#define AMR_FRAME 160 /* 20ms @ 8kHz */
#define AMR_MODE_MAX 7
#define AMR_NAMES "amr-nb", "anb"
#define AMR_RATE 8000
#define AMR_DESC "3GPP Adaptive Multi Rate Narrow-Band (AMR-NB) lossy speech compressor"
#ifdef DL_OPENCORE_AMRNB
#define AMR_FUNC LSX_DLENTRY_DYNAMIC
#else
#define AMR_FUNC LSX_DLENTRY_STATIC
#endif /* DL_AMRNB */
/* OpenCore definitions: */
#define AMR_OPENCORE 1
#define AMR_OPENCORE_ENABLE_ENCODE 1
#define AMR_OPENCORE_FUNC_ENTRIES(f,x) \
AMR_FUNC(f,x, void*, Encoder_Interface_init, (int dtx)) \
AMR_FUNC(f,x, int, Encoder_Interface_Encode, (void* state, enum amrnb_mode mode, const short* in, unsigned char* out, int forceSpeech)) \
AMR_FUNC(f,x, void, Encoder_Interface_exit, (void* state)) \
AMR_FUNC(f,x, void*, Decoder_Interface_init, (void)) \
AMR_FUNC(f,x, void, Decoder_Interface_Decode, (void* state, const unsigned char* in, short* out, int bfi)) \
AMR_FUNC(f,x, void, Decoder_Interface_exit, (void* state)) \
#define AmrEncoderInit() \
Encoder_Interface_init(1)
#define AmrEncoderEncode(state, mode, in, out, forceSpeech) \
Encoder_Interface_Encode(state, mode, in, out, forceSpeech)
#define AmrEncoderExit(state) \
Encoder_Interface_exit(state)
#define AmrDecoderInit() \
Decoder_Interface_init()
#define AmrDecoderDecode(state, in, out, bfi) \
Decoder_Interface_Decode(state, in, out, bfi)
#define AmrDecoderExit(state) \
Decoder_Interface_exit(state)
#define AMR_OPENCORE_DESC "amr-nb OpenCore library"
static const char* const amr_opencore_library_names[] =
{
#ifdef DL_OPENCORE_AMRNB
"libopencore-amrnb",
"libopencore-amrnb-0",
#endif
NULL
};
#include "amr.h"

@ -1,115 +0,0 @@
/* File format: AMR-WB (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
*/
/*
* In order to use the AMR format with SoX, you need to have an
* AMR library installed at SoX build time. The SoX build system
* recognizes the AMR implementations available from
* http://opencore-amr.sourceforge.net/
*/
#include "sox_i.h"
/* Common definitions: */
static const uint8_t amrwb_block_size[] = {18, 24, 33, 37, 41, 47, 51, 59, 61, 6, 6, 0, 0, 0, 1, 1};
static char const amrwb_magic[] = "#!AMR-WB\n";
#define amr_block_size amrwb_block_size
#define amr_magic amrwb_magic
#define amr_priv_t amrwb_priv_t
#define amr_opencore_funcs amrwb_opencore_funcs
#define amr_vo_funcs amrwb_vo_funcs
#define AMR_CODED_MAX 61 /* NB_SERIAL_MAX */
#define AMR_ENCODING SOX_ENCODING_AMR_WB
#define AMR_FORMAT_FN lsx_amr_wb_format_fn
#define AMR_FRAME 320 /* L_FRAME16k */
#define AMR_MODE_MAX 8
#define AMR_NAMES "amr-wb", "awb"
#define AMR_RATE 16000
#define AMR_DESC "3GPP Adaptive Multi Rate Wide-Band (AMR-WB) lossy speech compressor"
/* OpenCore definitions: */
#ifdef DL_OPENCORE_AMRWB
#define AMR_OC_FUNC LSX_DLENTRY_DYNAMIC
#else
#define AMR_OC_FUNC LSX_DLENTRY_STATIC
#endif
#if defined(HAVE_OPENCORE_AMRWB_DEC_IF_H) || defined(DL_OPENCORE_AMRWB)
#define AMR_OPENCORE 1
#define AMR_OPENCORE_ENABLE_ENCODE 0
#endif
#define AMR_OPENCORE_FUNC_ENTRIES(f,x) \
AMR_OC_FUNC(f,x, void*, D_IF_init, (void)) \
AMR_OC_FUNC(f,x, void, D_IF_decode, (void* state, const unsigned char* in, short* out, int bfi)) \
AMR_OC_FUNC(f,x, void, D_IF_exit, (void* state)) \
#define AmrDecoderInit() \
D_IF_init()
#define AmrDecoderDecode(state, in, out, bfi) \
D_IF_decode(state, in, out, bfi)
#define AmrDecoderExit(state) \
D_IF_exit(state)
#define AMR_OPENCORE_DESC "amr-wb OpenCore library"
static const char* const amr_opencore_library_names[] =
{
#ifdef DL_OPENCORE_AMRWB
"libopencore-amrwb",
"libopencore-amrwb-0",
#endif
NULL
};
/* VO definitions: */
#ifdef DL_VO_AMRWBENC
#define AMR_VO_FUNC LSX_DLENTRY_DYNAMIC
#else
#define AMR_VO_FUNC LSX_DLENTRY_STATIC
#endif
#if defined(HAVE_VO_AMRWBENC_ENC_IF_H) || defined(DL_VO_AMRWBENC)
#define AMR_VO 1
#endif
#define AMR_VO_FUNC_ENTRIES(f,x) \
AMR_VO_FUNC(f,x, void*, E_IF_init, (void)) \
AMR_VO_FUNC(f,x, int, E_IF_encode,(void* state, int16_t mode, int16_t* in, uint8_t* out, int16_t dtx)) \
AMR_VO_FUNC(f,x, void, E_IF_exit, (void* state)) \
#define AmrEncoderInit() \
E_IF_init()
#define AmrEncoderEncode(state, mode, in, out, forceSpeech) \
E_IF_encode(state, mode, in, out, forceSpeech)
#define AmrEncoderExit(state) \
E_IF_exit(state)
#define AMR_VO_DESC "amr-wb VisualOn library"
static const char* const amr_vo_library_names[] =
{
#ifdef DL_VO_AMRWBENC
"libvo-amrwbenc",
"libvo-amrwbenc-0",
#endif
NULL
};
#include "amr.h"

@ -1,335 +0,0 @@
/* File format: AMR (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
*/
#include <string.h>
#include <math.h>
#ifdef AMR_OPENCORE
LSX_DLENTRIES_TO_FUNCTIONS(AMR_OPENCORE_FUNC_ENTRIES)
typedef struct amr_opencore_funcs {
LSX_DLENTRIES_TO_PTRS(AMR_OPENCORE_FUNC_ENTRIES, amr_dl);
} amr_opencore_funcs;
#endif /* AMR_OPENCORE */
#ifdef AMR_VO
LSX_DLENTRIES_TO_FUNCTIONS(AMR_VO_FUNC_ENTRIES)
typedef struct amr_vo_funcs {
LSX_DLENTRIES_TO_PTRS(AMR_VO_FUNC_ENTRIES, amr_dl);
} amr_vo_funcs;
#endif /* AMR_VO */
#define AMR_CALL(p, func, args) ((p)->opencore.func args)
#ifdef AMR_VO
#define AMR_CALL_ENCODER(p, func, args) ((p)->vo.func args)
#else
#define AMR_CALL_ENCODER(p, func, args) ((p)->opencore.func args)
#endif
typedef struct amr_priv_t {
void* state;
unsigned mode;
size_t pcm_index;
#ifdef AMR_OPENCORE
amr_opencore_funcs opencore;
#endif /* AMR_OPENCORE */
#ifdef AMR_VO
amr_vo_funcs vo;
#endif /* AMR_VO */
short pcm[AMR_FRAME];
} priv_t;
#ifdef AMR_OPENCORE
static size_t decode_1_frame(sox_format_t * ft)
{
priv_t * p = (priv_t *)ft->priv;
size_t n;
uint8_t coded[AMR_CODED_MAX];
if (lsx_readbuf(ft, &coded[0], (size_t)1) != 1)
return AMR_FRAME;
n = amr_block_size[(coded[0] >> 3) & 0x0F];
if (!n) {
lsx_fail("invalid block type");
return AMR_FRAME;
}
n--;
if (lsx_readbuf(ft, &coded[1], n) != n)
return AMR_FRAME;
AMR_CALL(p, AmrDecoderDecode, (p->state, coded, p->pcm, 0));
return 0;
}
#endif
static int openlibrary(priv_t* p, int encoding)
{
int open_library_result;
(void)encoding;
#ifdef AMR_OPENCORE
if (AMR_OPENCORE_ENABLE_ENCODE || !encoding)
{
LSX_DLLIBRARY_TRYOPEN(
0,
&p->opencore,
amr_dl,
AMR_OPENCORE_FUNC_ENTRIES,
AMR_OPENCORE_DESC,
amr_opencore_library_names,
open_library_result);
if (!open_library_result)
return SOX_SUCCESS;
lsx_fail("Unable to open " AMR_OPENCORE_DESC);
return SOX_EOF;
}
#endif /* AMR_OPENCORE */
#ifdef AMR_VO
if (encoding) {
LSX_DLLIBRARY_TRYOPEN(
0,
&p->vo,
amr_dl,
AMR_VO_FUNC_ENTRIES,
AMR_VO_DESC,
amr_vo_library_names,
open_library_result);
if (!open_library_result)
return SOX_SUCCESS;
lsx_fail("Unable to open " AMR_VO_DESC);
}
#endif /* AMR_VO */
return SOX_EOF;
}
static void closelibrary(priv_t* p)
{
#ifdef AMR_OPENCORE
LSX_DLLIBRARY_CLOSE(&p->opencore, amr_dl);
#endif
#ifdef AMR_VO
LSX_DLLIBRARY_CLOSE(&p->vo, amr_dl);
#endif
}
#ifdef AMR_OPENCORE
static size_t amr_duration_frames(sox_format_t * ft)
{
off_t frame_size, data_start_offset = lsx_tell(ft);
size_t frames;
uint8_t coded;
for (frames = 0; lsx_readbuf(ft, &coded, (size_t)1) == 1; ++frames) {
frame_size = amr_block_size[coded >> 3 & 15];
if (!frame_size) {
lsx_fail("invalid block type");
break;
}
if (lsx_seeki(ft, frame_size - 1, SEEK_CUR)) {
lsx_fail("seek");
break;
}
}
lsx_debug("frames=%lu", (unsigned long)frames);
lsx_seeki(ft, data_start_offset, SEEK_SET);
return frames;
}
#endif
static int startread(sox_format_t * ft)
{
#if !defined(AMR_OPENCORE)
lsx_fail_errno(ft, SOX_EOF, "SoX was compiled without AMR-WB decoding support.");
return SOX_EOF;
#else
priv_t * p = (priv_t *)ft->priv;
char buffer[sizeof(amr_magic) - 1];
int open_library_result;
if (lsx_readchars(ft, buffer, sizeof(buffer)))
return SOX_EOF;
if (memcmp(buffer, amr_magic, sizeof(buffer))) {
lsx_fail_errno(ft, SOX_EHDR, "invalid magic number");
return SOX_EOF;
}
open_library_result = openlibrary(p, 0);
if (open_library_result != SOX_SUCCESS)
return open_library_result;
p->pcm_index = AMR_FRAME;
p->state = AMR_CALL(p, AmrDecoderInit, ());
if (!p->state)
{
closelibrary(p);
lsx_fail("AMR decoder failed to initialize.");
return SOX_EOF;
}
ft->signal.rate = AMR_RATE;
ft->encoding.encoding = AMR_ENCODING;
ft->signal.channels = 1;
ft->signal.length = ft->signal.length != SOX_IGNORE_LENGTH && ft->seekable?
(size_t)(amr_duration_frames(ft) * .02 * ft->signal.rate +.5) : SOX_UNSPEC;
return SOX_SUCCESS;
#endif
}
#ifdef AMR_OPENCORE
static size_t read_samples(sox_format_t * ft, sox_sample_t * buf, size_t len)
{
priv_t * p = (priv_t *)ft->priv;
size_t done;
for (done = 0; done < len; done++) {
if (p->pcm_index >= AMR_FRAME)
p->pcm_index = decode_1_frame(ft);
if (p->pcm_index >= AMR_FRAME)
break;
*buf++ = SOX_SIGNED_16BIT_TO_SAMPLE(p->pcm[p->pcm_index++], ft->clips);
}
return done;
}
static int stopread(sox_format_t * ft)
{
priv_t * p = (priv_t *)ft->priv;
AMR_CALL(p, AmrDecoderExit, (p->state));
closelibrary(p);
return SOX_SUCCESS;
}
#else
#define read_samples NULL
#define stopread NULL
#endif
static int startwrite(sox_format_t * ft)
{
#if !defined(AMR_VO) && !AMR_OPENCORE_ENABLE_ENCODE
lsx_fail_errno(ft, SOX_EOF, "SoX was compiled without AMR-WB encoding support.");
return SOX_EOF;
#else
priv_t * p = (priv_t *)ft->priv;
int open_library_result;
if (ft->encoding.compression != HUGE_VAL) {
p->mode = (unsigned)ft->encoding.compression;
if (p->mode != ft->encoding.compression || p->mode > AMR_MODE_MAX) {
lsx_fail_errno(ft, SOX_EINVAL, "compression level must be a whole number from 0 to %i", AMR_MODE_MAX);
return SOX_EOF;
}
}
else p->mode = 0;
open_library_result = openlibrary(p, 1);
if (open_library_result != SOX_SUCCESS)
return open_library_result;
p->state = AMR_CALL_ENCODER(p, AmrEncoderInit, ());
if (!p->state)
{
closelibrary(p);
lsx_fail("AMR encoder failed to initialize.");
return SOX_EOF;
}
lsx_writes(ft, amr_magic);
p->pcm_index = 0;
return SOX_SUCCESS;
#endif
}
#if defined(AMR_VO) || AMR_OPENCORE_ENABLE_ENCODE
static sox_bool encode_1_frame(sox_format_t * ft)
{
priv_t * p = (priv_t *)ft->priv;
uint8_t coded[AMR_CODED_MAX];
int n = AMR_CALL_ENCODER(p, AmrEncoderEncode, (p->state, p->mode, p->pcm, coded, 1));
sox_bool result = lsx_writebuf(ft, coded, (size_t) (size_t) (unsigned)n) == (unsigned)n;
if (!result)
lsx_fail_errno(ft, errno, "write error");
return result;
}
static size_t write_samples(sox_format_t * ft, const sox_sample_t * buf, size_t len)
{
priv_t * p = (priv_t *)ft->priv;
size_t done;
for (done = 0; done < len; ++done) {
SOX_SAMPLE_LOCALS;
p->pcm[p->pcm_index++] = SOX_SAMPLE_TO_SIGNED_16BIT(*buf++, ft->clips);
if (p->pcm_index == AMR_FRAME) {
p->pcm_index = 0;
if (!encode_1_frame(ft))
return 0;
}
}
return done;
}
static int stopwrite(sox_format_t * ft)
{
priv_t * p = (priv_t *)ft->priv;
int result = SOX_SUCCESS;
if (p->pcm_index) {
do {
p->pcm[p->pcm_index++] = 0;
} while (p->pcm_index < AMR_FRAME);
if (!encode_1_frame(ft))
result = SOX_EOF;
}
AMR_CALL_ENCODER(p, AmrEncoderExit, (p->state));
return result;
}
#else
#define write_samples NULL
#define stopwrite NULL
#endif /* defined(AMR_VO) || AMR_OPENCORE_ENABLE_ENCODE */
sox_format_handler_t const * AMR_FORMAT_FN(void);
sox_format_handler_t const * AMR_FORMAT_FN(void)
{
static char const * const names[] = {AMR_NAMES, NULL};
static sox_rate_t const write_rates[] = {AMR_RATE, 0};
static unsigned const write_encodings[] = {AMR_ENCODING, 0, 0};
static sox_format_handler_t handler = {
SOX_LIB_VERSION_CODE,
AMR_DESC,
names, SOX_FILE_MONO,
startread, read_samples, stopread,
startwrite, write_samples, stopwrite,
NULL, write_encodings, write_rates, sizeof(priv_t)
};
return &handler;
}

@ -1,47 +0,0 @@
/* libSoX Bandpass effect file. July 5, 1991
* Copyright 1991 Lance Norskog And Sundry Contributors
*
* This source code is freely redistributable and may be used for
* any purpose. This copyright notice must be maintained.
* Lance Norskog And Sundry Contributors are not responsible for
* the consequences of using this software.
*
* Algorithm: 2nd order recursive filter.
* Formula stolen from MUSIC56K, a toolkit of 56000 assembler stuff.
* Quote:
* This is a 2nd order recursive band pass filter of the form.
* y(n)= a * x(n) - b * y(n-1) - c * y(n-2)
* where :
* x(n) = "IN"
* "OUT" = y(n)
* c = EXP(-2*pi*cBW/S_RATE)
* b = -4*c/(1+c)*COS(2*pi*cCF/S_RATE)
* if cSCL=2 (i.e. noise input)
* a = SQT(((1+c)*(1+c)-b*b)*(1-c)/(1+c))
* else
* a = SQT(1-b*b/(4*c))*(1-c)
* endif
* note : cCF is the center frequency in Hertz
* cBW is the band width in Hertz
* cSCL is a scale factor, use 1 for pitched sounds
* use 2 for noise.
*
*
* July 1, 1999 - Jan Paul Schmidt <jps@fundament.org>
*
* This looks like the resonator band pass in SPKit. It's a
* second order all-pole (IIR) band-pass filter described
* at the pages 186 - 189 in
* Dodge, Charles & Jerse, Thomas A. 1985:
* Computer Music -- Synthesis, Composition and Performance.
* New York: Schirmer Books.
* Reference from the SPKit manual.
*/
p->a2 = exp(-2 * M_PI * bw_Hz / effp->in_signal.rate);
p->a1 = -4 * p->a2 / (1 + p->a2) * cos(2 * M_PI * p->fc / effp->in_signal.rate);
p->b0 = sqrt(1 - p->a1 * p->a1 / (4 * p->a2)) * (1 - p->a2);
if (p->filter_type == filter_BPF_SPK_N) {
mult = sqrt(((1+p->a2) * (1+p->a2) - p->a1*p->a1) * (1-p->a2) / (1+p->a2)) / p->b0;
p->b0 *= mult;
}

@ -1,325 +0,0 @@
/* libSoX effect: Pitch Bend (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
*/
/* Portions based on http://www.dspdimension.com/download smbPitchShift.cpp:
*
* COPYRIGHT 1999-2006 Stephan M. Bernsee <smb [AT] dspdimension [DOT] com>
*
* The Wide Open License (WOL)
*
* Permission to use, copy, modify, distribute and sell this software and its
* documentation for any purpose is hereby granted without fee, provided that
* the above copyright notice and this license appear in all source copies.
* THIS SOFTWARE IS PROVIDED "AS IS" WITHOUT EXPRESS OR IMPLIED WARRANTY OF
* ANY KIND. See http://www.dspguru.com/wol.htm for more information.
*/
#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>
#define MAX_FRAME_LENGTH 8192
typedef struct {
unsigned nbends; /* Number of bends requested */
struct {
char *str; /* Command-line argument to parse for this bend */
uint64_t start; /* Start bending when in_pos equals this */
double cents;
uint64_t duration; /* Number of samples to bend */
} *bends;
unsigned frame_rate;
size_t in_pos; /* Number of samples read from the input stream */
unsigned bends_pos; /* Number of bends completed so far */
double shift;
float gInFIFO[MAX_FRAME_LENGTH];
float gOutFIFO[MAX_FRAME_LENGTH];
double gFFTworksp[2 * MAX_FRAME_LENGTH];
float gLastPhase[MAX_FRAME_LENGTH / 2 + 1];
float gSumPhase[MAX_FRAME_LENGTH / 2 + 1];
float gOutputAccum[2 * MAX_FRAME_LENGTH];
float gAnaFreq[MAX_FRAME_LENGTH];
float gAnaMagn[MAX_FRAME_LENGTH];
float gSynFreq[MAX_FRAME_LENGTH];
float gSynMagn[MAX_FRAME_LENGTH];
long gRover;
int fftFrameSize, ovsamp;
} priv_t;
static int parse(sox_effect_t * effp, char **argv, sox_rate_t rate)
{
priv_t *p = (priv_t *) effp->priv;
size_t i;
char const *next;
uint64_t last_seen = 0;
const uint64_t in_length = argv ? 0 :
(effp->in_signal.length != SOX_UNKNOWN_LEN ?
effp->in_signal.length / effp->in_signal.channels : SOX_UNKNOWN_LEN);
for (i = 0; i < p->nbends; ++i) {
if (argv) /* 1st parse only */
p->bends[i].str = lsx_strdup(argv[i]);
next = lsx_parseposition(rate, p->bends[i].str,
argv ? NULL : &p->bends[i].start, last_seen, in_length, '+');
last_seen = p->bends[i].start;
if (next == NULL || *next != ',')
break;
p->bends[i].cents = strtod(next + 1, (char **)&next);
if (p->bends[i].cents == 0 || *next != ',')
break;
next = lsx_parseposition(rate, next + 1,
argv ? NULL : &p->bends[i].duration, last_seen, in_length, '+');
last_seen = p->bends[i].duration;
if (next == NULL || *next != '\0')
break;
/* sanity checks */
if (!argv && p->bends[i].duration < p->bends[i].start) {
lsx_fail("Bend %" PRIuPTR " has negative width", i+1);
break;
}
if (!argv && i && p->bends[i].start < p->bends[i-1].start) {
lsx_fail("Bend %" PRIuPTR " overlaps with previous one", i+1);
break;
}
p->bends[i].duration -= p->bends[i].start;
}
if (i < p->nbends)
return lsx_usage(effp);
return SOX_SUCCESS;
}
static int create(sox_effect_t * effp, int argc, char **argv)
{
priv_t *p = (priv_t *) effp->priv;
char const * opts = "f:o:";
int c;
lsx_getopt_t optstate;
lsx_getopt_init(argc, argv, opts, NULL, lsx_getopt_flag_none, 1, &optstate);
p->frame_rate = 25;
p->ovsamp = 16;
while ((c = lsx_getopt(&optstate)) != -1) switch (c) {
GETOPT_NUMERIC(optstate, 'f', frame_rate, 10 , 80)
GETOPT_NUMERIC(optstate, 'o', ovsamp, 4 , 32)
default: lsx_fail("unknown option `-%c'", optstate.opt); return lsx_usage(effp);
}
argc -= optstate.ind, argv += optstate.ind;
p->nbends = argc;
p->bends = lsx_calloc(p->nbends, sizeof(*p->bends));
return parse(effp, argv, 0.); /* No rate yet; parse with dummy */
}
static int start(sox_effect_t * effp)
{
priv_t *p = (priv_t *) effp->priv;
unsigned i;
int n = effp->in_signal.rate / p->frame_rate + .5;
for (p->fftFrameSize = 2; n > 2; p->fftFrameSize <<= 1, n >>= 1);
assert(p->fftFrameSize <= MAX_FRAME_LENGTH);
p->shift = 1;
parse(effp, 0, effp->in_signal.rate); /* Re-parse now rate is known */
p->in_pos = p->bends_pos = 0;
for (i = 0; i < p->nbends; ++i)
if (p->bends[i].duration)
return SOX_SUCCESS;
return SOX_EFF_NULL;
}
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, len = *isamp = *osamp = min(*isamp, *osamp);
double magn, phase, tmp, window, real, imag;
double freqPerBin, expct;
long k, qpd, index, inFifoLatency, stepSize, fftFrameSize2;
float pitchShift = p->shift;
/* set up some handy variables */
fftFrameSize2 = p->fftFrameSize / 2;
stepSize = p->fftFrameSize / p->ovsamp;
freqPerBin = effp->in_signal.rate / p->fftFrameSize;
expct = 2. * M_PI * (double) stepSize / (double) p->fftFrameSize;
inFifoLatency = p->fftFrameSize - stepSize;
if (!p->gRover)
p->gRover = inFifoLatency;
/* main processing loop */
for (i = 0; i < len; i++) {
SOX_SAMPLE_LOCALS;
++p->in_pos;
/* As long as we have not yet collected enough data just read in */
p->gInFIFO[p->gRover] = SOX_SAMPLE_TO_FLOAT_32BIT(ibuf[i], effp->clips);
obuf[i] = SOX_FLOAT_32BIT_TO_SAMPLE(
p->gOutFIFO[p->gRover - inFifoLatency], effp->clips);
p->gRover++;
/* now we have enough data for processing */
if (p->gRover >= p->fftFrameSize) {
if (p->bends_pos != p->nbends && p->in_pos >=
p->bends[p->bends_pos].start + p->bends[p->bends_pos].duration) {
pitchShift = p->shift *= pow(2., p->bends[p->bends_pos].cents / 1200);
++p->bends_pos;
}
if (p->bends_pos != p->nbends && p->in_pos >= p->bends[p->bends_pos].start) {
double progress = (double)(p->in_pos - p->bends[p->bends_pos].start) /
p->bends[p->bends_pos].duration;
progress = 1 - cos(M_PI * progress);
progress *= p->bends[p->bends_pos].cents * (.5 / 1200);
pitchShift = p->shift * pow(2., progress);
}
p->gRover = inFifoLatency;
/* do windowing and re,im interleave */
for (k = 0; k < p->fftFrameSize; k++) {
window = -.5 * cos(2 * M_PI * k / (double) p->fftFrameSize) + .5;
p->gFFTworksp[2 * k] = p->gInFIFO[k] * window;
p->gFFTworksp[2 * k + 1] = 0.;
}
/* ***************** ANALYSIS ******************* */
lsx_safe_cdft(2 * p->fftFrameSize, 1, p->gFFTworksp);
/* this is the analysis step */
for (k = 0; k <= fftFrameSize2; k++) {
/* de-interlace FFT buffer */
real = p->gFFTworksp[2 * k];
imag = - p->gFFTworksp[2 * k + 1];
/* compute magnitude and phase */
magn = 2. * sqrt(real * real + imag * imag);
phase = atan2(imag, real);
/* compute phase difference */
tmp = phase - p->gLastPhase[k];
p->gLastPhase[k] = phase;
tmp -= (double) k *expct; /* subtract expected phase difference */
/* map delta phase into +/- Pi interval */
qpd = tmp / M_PI;
if (qpd >= 0)
qpd += qpd & 1;
else qpd -= qpd & 1;
tmp -= M_PI * (double) qpd;
/* get deviation from bin frequency from the +/- Pi interval */
tmp = p->ovsamp * tmp / (2. * M_PI);
/* compute the k-th partials' true frequency */
tmp = (double) k *freqPerBin + tmp * freqPerBin;
/* store magnitude and true frequency in analysis arrays */
p->gAnaMagn[k] = magn;
p->gAnaFreq[k] = tmp;
}
/* this does the actual pitch shifting */
memset(p->gSynMagn, 0, p->fftFrameSize * sizeof(float));
memset(p->gSynFreq, 0, p->fftFrameSize * sizeof(float));
for (k = 0; k <= fftFrameSize2; k++) {
index = k * pitchShift;
if (index <= fftFrameSize2) {
p->gSynMagn[index] += p->gAnaMagn[k];
p->gSynFreq[index] = p->gAnaFreq[k] * pitchShift;
}
}
for (k = 0; k <= fftFrameSize2; k++) { /* SYNTHESIS */
/* get magnitude and true frequency from synthesis arrays */
magn = p->gSynMagn[k], tmp = p->gSynFreq[k];
tmp -= (double) k *freqPerBin; /* subtract bin mid frequency */
tmp /= freqPerBin; /* get bin deviation from freq deviation */
tmp = 2. * M_PI * tmp / p->ovsamp; /* take p->ovsamp into account */
tmp += (double) k *expct; /* add the overlap phase advance back in */
p->gSumPhase[k] += tmp; /* accumulate delta phase to get bin phase */
phase = p->gSumPhase[k];
/* get real and imag part and re-interleave */
p->gFFTworksp[2 * k] = magn * cos(phase);
p->gFFTworksp[2 * k + 1] = - magn * sin(phase);
}
for (k = p->fftFrameSize + 2; k < 2 * p->fftFrameSize; k++)
p->gFFTworksp[k] = 0.; /* zero negative frequencies */
lsx_safe_cdft(2 * p->fftFrameSize, -1, p->gFFTworksp);
/* do windowing and add to output accumulator */
for (k = 0; k < p->fftFrameSize; k++) {
window =
-.5 * cos(2. * M_PI * (double) k / (double) p->fftFrameSize) + .5;
p->gOutputAccum[k] +=
2. * window * p->gFFTworksp[2 * k] / (fftFrameSize2 * p->ovsamp);
}
for (k = 0; k < stepSize; k++)
p->gOutFIFO[k] = p->gOutputAccum[k];
memmove(p->gOutputAccum, /* shift accumulator */
p->gOutputAccum + stepSize, p->fftFrameSize * sizeof(float));
for (k = 0; k < inFifoLatency; k++) /* move input FIFO */
p->gInFIFO[k] = p->gInFIFO[k + stepSize];
}
}
return SOX_SUCCESS;
}
static int stop(sox_effect_t * effp)
{
priv_t *p = (priv_t *) effp->priv;
if (p->bends_pos != p->nbends)
lsx_warn("Input audio too short; bends not applied: %u",
p->nbends - p->bends_pos);
return SOX_SUCCESS;
}
static int lsx_kill(sox_effect_t * effp)
{
priv_t *p = (priv_t *) effp->priv;
unsigned i;
for (i = 0; i < p->nbends; ++i)
free(p->bends[i].str);
free(p->bends);
return SOX_SUCCESS;
}
sox_effect_handler_t const *lsx_bend_effect_fn(void)
{
static sox_effect_handler_t handler = {
"bend", "[-f frame-rate(25)] [-o over-sample(16)] {start,cents,end}",
0, create, start, flow, 0, stop, lsx_kill, sizeof(priv_t)
};
return &handler;
}

@ -1,178 +0,0 @@
/* libSoX Biquad filter common functions (c) 2006-7 robs@users.sourceforge.net
*
* This library is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation; either version 2.1 of the License, or (at
* your option) any later version.
*
* This library is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser
* General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this library; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "biquad.h"
#include <string.h>
typedef biquad_t priv_t;
static char const * const width_str[] = {
"band-width(Hz)",
"band-width(kHz)",
"band-width(Hz, no warp)", /* deprecated */
"band-width(octaves)",
"Q",
"slope",
};
static char const all_width_types[] = "hkboqs";
int lsx_biquad_getopts(sox_effect_t * effp, int argc, char **argv,
int min_args, int max_args, int fc_pos, int width_pos, int gain_pos,
char const * allowed_width_types, filter_t filter_type)
{
priv_t * p = (priv_t *)effp->priv;
char width_type = *allowed_width_types;
char dummy, * dummy_p; /* To check for extraneous chars. */
--argc, ++argv;
p->filter_type = filter_type;
if (argc < min_args || argc > max_args ||
(argc > fc_pos && ((p->fc = lsx_parse_frequency(argv[fc_pos], &dummy_p)) <= 0 || *dummy_p)) ||
(argc > width_pos && ((unsigned)(sscanf(argv[width_pos], "%lf%c %c", &p->width, &width_type, &dummy)-1) > 1 || p->width <= 0)) ||
(argc > gain_pos && sscanf(argv[gain_pos], "%lf %c", &p->gain, &dummy) != 1) ||
!strchr(allowed_width_types, width_type) || (width_type == 's' && p->width > 1))
return lsx_usage(effp);
p->width_type = strchr(all_width_types, width_type) - all_width_types;
if ((size_t)p->width_type >= strlen(all_width_types))
p->width_type = 0;
if (p->width_type == width_bw_kHz) {
p->width *= 1000;
p->width_type = width_bw_Hz;
}
return SOX_SUCCESS;
}
static int start(sox_effect_t * effp)
{
priv_t * p = (priv_t *)effp->priv;
/* Simplify: */
p->b2 /= p->a0;
p->b1 /= p->a0;
p->b0 /= p->a0;
p->a2 /= p->a0;
p->a1 /= p->a0;
p->o2 = p->o1 = p->i2 = p->i1 = 0;
return SOX_SUCCESS;
}
int lsx_biquad_start(sox_effect_t * effp)
{
priv_t * p = (priv_t *)effp->priv;
start(effp);
if (effp->global_info->plot == sox_plot_octave) {
printf(
"%% GNU Octave file (may also work with MATLAB(R) )\n"
"Fs=%g;minF=10;maxF=Fs/2;\n"
"sweepF=logspace(log10(minF),log10(maxF),200);\n"
"[h,w]=freqz([%.15e %.15e %.15e],[1 %.15e %.15e],sweepF,Fs);\n"
"semilogx(w,20*log10(h))\n"
"title('SoX effect: %s gain=%g frequency=%g %s=%g (rate=%g)')\n"
"xlabel('Frequency (Hz)')\n"
"ylabel('Amplitude Response (dB)')\n"
"axis([minF maxF -35 25])\n"
"grid on\n"
"disp('Hit return to continue')\n"
"pause\n"
, effp->in_signal.rate, p->b0, p->b1, p->b2, p->a1, p->a2
, effp->handler.name, p->gain, p->fc, width_str[p->width_type], p->width
, effp->in_signal.rate);
return SOX_EOF;
}
if (effp->global_info->plot == sox_plot_gnuplot) {
printf(
"# gnuplot file\n"
"set title 'SoX effect: %s gain=%g frequency=%g %s=%g (rate=%g)'\n"
"set xlabel 'Frequency (Hz)'\n"
"set ylabel 'Amplitude Response (dB)'\n"
"Fs=%g\n"
"b0=%.15e; b1=%.15e; b2=%.15e; a1=%.15e; a2=%.15e\n"
"o=2*pi/Fs\n"
"H(f)=sqrt((b0*b0+b1*b1+b2*b2+2.*(b0*b1+b1*b2)*cos(f*o)+2.*(b0*b2)*cos(2.*f*o))/(1.+a1*a1+a2*a2+2.*(a1+a1*a2)*cos(f*o)+2.*a2*cos(2.*f*o)))\n"
"set logscale x\n"
"set samples 250\n"
"set grid xtics ytics\n"
"set key off\n"
"plot [f=10:Fs/2] [-35:25] 20*log10(H(f))\n"
"pause -1 'Hit return to continue'\n"
, effp->handler.name, p->gain, p->fc, width_str[p->width_type], p->width
, effp->in_signal.rate, effp->in_signal.rate
, p->b0, p->b1, p->b2, p->a1, p->a2);
return SOX_EOF;
}
if (effp->global_info->plot == sox_plot_data) {
printf("# SoX effect: %s gain=%g frequency=%g %s=%g (rate=%g)\n"
"# IIR filter\n"
"# rate: %g\n"
"# name: b\n"
"# type: matrix\n"
"# rows: 3\n"
"# columns: 1\n"
"%24.16e\n%24.16e\n%24.16e\n"
"# name: a\n"
"# type: matrix\n"
"# rows: 3\n"
"# columns: 1\n"
"%24.16e\n%24.16e\n%24.16e\n"
, effp->handler.name, p->gain, p->fc, width_str[p->width_type], p->width
, effp->in_signal.rate, effp->in_signal.rate
, p->b0, p->b1, p->b2, 1. /* a0 */, p->a1, p->a2);
return SOX_EOF;
}
return SOX_SUCCESS;
}
int lsx_biquad_flow(sox_effect_t * effp, const sox_sample_t *ibuf,
sox_sample_t *obuf, size_t *isamp, size_t *osamp)
{
priv_t * p = (priv_t *)effp->priv;
size_t len = *isamp = *osamp = min(*isamp, *osamp);
while (len--) {
double o0 = *ibuf*p->b0 + p->i1*p->b1 + p->i2*p->b2 - p->o1*p->a1 - p->o2*p->a2;
p->i2 = p->i1, p->i1 = *ibuf++;
p->o2 = p->o1, p->o1 = o0;
*obuf++ = SOX_ROUND_CLIP_COUNT(o0, effp->clips);
}
return SOX_SUCCESS;
}
static int create(sox_effect_t * effp, int argc, char * * argv)
{
priv_t * p = (priv_t *)effp->priv;
double * d = &p->b0;
char c;
--argc, ++argv;
if (argc == 6)
for (; argc && sscanf(*argv, "%lf%c", d, &c) == 1; --argc, ++argv, ++d);
return argc? lsx_usage(effp) : SOX_SUCCESS;
}
sox_effect_handler_t const * lsx_biquad_effect_fn(void)
{
static sox_effect_handler_t handler = {
"biquad", "b0 b1 b2 a0 a1 a2", 0,
create, lsx_biquad_start, lsx_biquad_flow, NULL, NULL, NULL, sizeof(priv_t)
};
return &handler;
}

@ -1,78 +0,0 @@
/* libSoX Biquad filter common definitions (c) 2006-7 robs@users.sourceforge.net
*
* This library is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation; either version 2.1 of the License, or (at
* your option) any later version.
*
* This library is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser
* General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this library; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef biquad_included
#define biquad_included
#define LSX_EFF_ALIAS
#include "sox_i.h"
typedef enum {
filter_LPF,
filter_HPF,
filter_BPF_CSG,
filter_BPF,
filter_notch,
filter_APF,
filter_peakingEQ,
filter_lowShelf,
filter_highShelf,
filter_LPF_1,
filter_HPF_1,
filter_BPF_SPK,
filter_BPF_SPK_N,
filter_AP1,
filter_AP2,
filter_deemph,
filter_riaa
} filter_t;
typedef enum {
width_bw_Hz,
width_bw_kHz,
/* The old, non-RBJ, non-freq-warped band-pass/reject response;
* leaving here for now just in case anybody misses it: */
width_bw_old,
width_bw_oct,
width_Q,
width_slope
} width_t;
/* Private data for the biquad filter effects */
typedef struct {
double gain; /* For EQ filters */
double fc; /* Centre/corner/cutoff frequency */
double width; /* Filter width; interpreted as per width_type */
width_t width_type;
filter_t filter_type;
double b0, b1, b2; /* Filter coefficients */
double a0, a1, a2; /* Filter coefficients */
sox_sample_t i1, i2; /* Filter memory */
double o1, o2; /* Filter memory */
} biquad_t;
int lsx_biquad_getopts(sox_effect_t * effp, int n, char **argv,
int min_args, int max_args, int fc_pos, int width_pos, int gain_pos,
char const * allowed_width_types, filter_t filter_type);
int lsx_biquad_start(sox_effect_t * effp);
int lsx_biquad_flow(sox_effect_t * effp, const sox_sample_t *ibuf, sox_sample_t *obuf,
size_t *isamp, size_t *osamp);
#endif

@ -1,416 +0,0 @@
/* libSoX Biquad filter effects (c) 2006-8 robs@users.sourceforge.net
*
* This library is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation; either version 2.1 of the License, or (at
* your option) any later version.
*
* This library is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser
* General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this library; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
*
* 2-pole filters designed by Robert Bristow-Johnson <rbj@audioimagination.com>
* see https://webaudio.github.io/Audio-EQ-Cookbook/audio-eq-cookbook.html
*
* 1-pole filters based on code (c) 2000 Chris Bagwell <cbagwell@sprynet.com>
* Algorithms: Recursive single pole low/high pass filter
* Reference: The Scientist and Engineer's Guide to Digital Signal Processing
*
* low-pass: output[N] = input[N] * A + output[N-1] * B
* X = exp(-2.0 * pi * Fc)
* A = 1 - X
* B = X
* Fc = cutoff freq / sample rate
*
* Mimics an RC low-pass filter:
*
* ---/\/\/\/\----------->
* |
* --- C
* ---
* |
* |
* V
*
* high-pass: output[N] = A0 * input[N] + A1 * input[N-1] + B1 * output[N-1]
* X = exp(-2.0 * pi * Fc)
* A0 = (1 + X) / 2
* A1 = -(1 + X) / 2
* B1 = X
* Fc = cutoff freq / sample rate
*
* Mimics an RC high-pass filter:
*
* || C
* ----||--------->
* || |
* <
* > R
* <
* |
* V
*/
#include "biquad.h"
#include <assert.h>
#include <string.h>
typedef biquad_t priv_t;
static int hilo1_getopts(sox_effect_t * effp, int argc, char **argv) {
return lsx_biquad_getopts(effp, argc, argv, 1, 1, 0, 1, 2, "",
*effp->handler.name == 'l'? filter_LPF_1 : filter_HPF_1);
}
static int hilo2_getopts(sox_effect_t * effp, int argc, char **argv) {
priv_t * p = (priv_t *)effp->priv;
if (argc > 1 && strcmp(argv[1], "-1") == 0)
return hilo1_getopts(effp, argc - 1, argv + 1);
if (argc > 1 && strcmp(argv[1], "-2") == 0)
++argv, --argc;
p->width = sqrt(0.5); /* Default to Butterworth */
return lsx_biquad_getopts(effp, argc, argv, 1, 2, 0, 1, 2, "qohk",
*effp->handler.name == 'l'? filter_LPF : filter_HPF);
}
static int bandpass_getopts(sox_effect_t * effp, int argc, char **argv) {
filter_t type = filter_BPF;
if (argc > 1 && strcmp(argv[1], "-c") == 0)
++argv, --argc, type = filter_BPF_CSG;
return lsx_biquad_getopts(effp, argc, argv, 2, 2, 0, 1, 2, "hkqob", type);
}
static int bandrej_getopts(sox_effect_t * effp, int argc, char **argv) {
return lsx_biquad_getopts(effp, argc, argv, 2, 2, 0, 1, 2, "hkqob", filter_notch);
}
static int allpass_getopts(sox_effect_t * effp, int argc, char **argv) {
filter_t type = filter_APF;
int m;
if (argc > 1 && strcmp(argv[1], "-1") == 0)
++argv, --argc, type = filter_AP1;
else if (argc > 1 && strcmp(argv[1], "-2") == 0)
++argv, --argc, type = filter_AP2;
m = 1 + (type == filter_APF);
return lsx_biquad_getopts(effp, argc, argv, m, m, 0, 1, 2, "hkqo", type);
}
static int tone_getopts(sox_effect_t * effp, int argc, char **argv) {
priv_t * p = (priv_t *)effp->priv;
p->width = 0.5;
p->fc = *effp->handler.name == 'b'? 100 : 3000;
return lsx_biquad_getopts(effp, argc, argv, 1, 3, 1, 2, 0, "shkqo",
*effp->handler.name == 'b'? filter_lowShelf: filter_highShelf);
}
static int equalizer_getopts(sox_effect_t * effp, int argc, char **argv) {
return lsx_biquad_getopts(effp, argc, argv, 3, 3, 0, 1, 2, "qohk", filter_peakingEQ);
}
static int band_getopts(sox_effect_t * effp, int argc, char **argv) {
filter_t type = filter_BPF_SPK;
if (argc > 1 && strcmp(argv[1], "-n") == 0)
++argv, --argc, type = filter_BPF_SPK_N;
return lsx_biquad_getopts(effp, argc, argv, 1, 2, 0, 1, 2, "hkqo", type);
}
static int deemph_getopts(sox_effect_t * effp, int argc, char **argv) {
return lsx_biquad_getopts(effp, argc, argv, 0, 0, 0, 1, 2, "s", filter_deemph);
}
static int riaa_getopts(sox_effect_t * effp, int argc, char **argv) {
priv_t * p = (priv_t *)effp->priv;
p->filter_type = filter_riaa;
(void)argv;
return --argc? lsx_usage(effp) : SOX_SUCCESS;
}
static void make_poly_from_roots(
double const * roots, size_t num_roots, double * poly)
{
size_t i, j;
poly[0] = 1;
poly[1] = -roots[0];
memset(poly + 2, 0, (num_roots + 1 - 2) * sizeof(*poly));
for (i = 1; i < num_roots; ++i)
for (j = num_roots; j > 0; --j)
poly[j] -= poly[j - 1] * roots[i];
}
static int start(sox_effect_t * effp)
{
priv_t * p = (priv_t *)effp->priv;
double w0, A, alpha, mult;
if (p->filter_type == filter_deemph) { /* See deemph.plt for documentation */
if (effp->in_signal.rate == 44100) {
p->fc = 5283;
p->width = 0.4845;
p->gain = -9.477;
}
else if (effp->in_signal.rate == 48000) {
p->fc = 5356;
p->width = 0.479;
p->gain = -9.62;
}
else {
lsx_fail("sample rate must be 44100 (audio-CD) or 48000 (DAT)");
return SOX_EOF;
}
}
w0 = 2 * M_PI * p->fc / effp->in_signal.rate;
A = exp(p->gain / 40 * log(10.));
alpha = 0, mult = dB_to_linear(max(p->gain, 0));
if (w0 > M_PI) {
lsx_fail("frequency must be less than half the sample-rate (Nyquist rate)");
return SOX_EOF;
}
/* Set defaults: */
p->b0 = p->b1 = p->b2 = p->a1 = p->a2 = 0;
p->a0 = 1;
if (p->width) switch (p->width_type) {
case width_slope:
alpha = sin(w0)/2 * sqrt((A + 1/A)*(1/p->width - 1) + 2);
break;
case width_Q:
alpha = sin(w0)/(2*p->width);
break;
case width_bw_oct:
alpha = sin(w0)*sinh(log(2.)/2 * p->width * w0/sin(w0));
break;
case width_bw_Hz:
alpha = sin(w0)/(2*p->fc/p->width);
break;
case width_bw_kHz: assert(0); /* Shouldn't get here */
case width_bw_old:
alpha = tan(M_PI * p->width / effp->in_signal.rate);
break;
}
switch (p->filter_type) {
case filter_LPF: /* H(s) = 1 / (s^2 + s/Q + 1) */
p->b0 = (1 - cos(w0))/2;
p->b1 = 1 - cos(w0);
p->b2 = (1 - cos(w0))/2;
p->a0 = 1 + alpha;
p->a1 = -2*cos(w0);
p->a2 = 1 - alpha;
break;
case filter_HPF: /* H(s) = s^2 / (s^2 + s/Q + 1) */
p->b0 = (1 + cos(w0))/2;
p->b1 = -(1 + cos(w0));
p->b2 = (1 + cos(w0))/2;
p->a0 = 1 + alpha;
p->a1 = -2*cos(w0);
p->a2 = 1 - alpha;
break;
case filter_BPF_CSG: /* H(s) = s / (s^2 + s/Q + 1) (constant skirt gain, peak gain = Q) */
p->b0 = sin(w0)/2;
p->b1 = 0;
p->b2 = -sin(w0)/2;
p->a0 = 1 + alpha;
p->a1 = -2*cos(w0);
p->a2 = 1 - alpha;
break;
case filter_BPF: /* H(s) = (s/Q) / (s^2 + s/Q + 1) (constant 0 dB peak gain) */
p->b0 = alpha;
p->b1 = 0;
p->b2 = -alpha;
p->a0 = 1 + alpha;
p->a1 = -2*cos(w0);
p->a2 = 1 - alpha;
break;
case filter_notch: /* H(s) = (s^2 + 1) / (s^2 + s/Q + 1) */
p->b0 = 1;
p->b1 = -2*cos(w0);
p->b2 = 1;
p->a0 = 1 + alpha;
p->a1 = -2*cos(w0);
p->a2 = 1 - alpha;
break;
case filter_APF: /* H(s) = (s^2 - s/Q + 1) / (s^2 + s/Q + 1) */
p->b0 = 1 - alpha;
p->b1 = -2*cos(w0);
p->b2 = 1 + alpha;
p->a0 = 1 + alpha;
p->a1 = -2*cos(w0);
p->a2 = 1 - alpha;
break;
case filter_peakingEQ: /* H(s) = (s^2 + s*(A/Q) + 1) / (s^2 + s/(A*Q) + 1) */
if (A == 1)
return SOX_EFF_NULL;
p->b0 = 1 + alpha*A;
p->b1 = -2*cos(w0);
p->b2 = 1 - alpha*A;
p->a0 = 1 + alpha/A;
p->a1 = -2*cos(w0);
p->a2 = 1 - alpha/A;
break;
case filter_lowShelf: /* H(s) = A * (s^2 + (sqrt(A)/Q)*s + A)/(A*s^2 + (sqrt(A)/Q)*s + 1) */
if (A == 1)
return SOX_EFF_NULL;
p->b0 = A*( (A+1) - (A-1)*cos(w0) + 2*sqrt(A)*alpha );
p->b1 = 2*A*( (A-1) - (A+1)*cos(w0) );
p->b2 = A*( (A+1) - (A-1)*cos(w0) - 2*sqrt(A)*alpha );
p->a0 = (A+1) + (A-1)*cos(w0) + 2*sqrt(A)*alpha;
p->a1 = -2*( (A-1) + (A+1)*cos(w0) );
p->a2 = (A+1) + (A-1)*cos(w0) - 2*sqrt(A)*alpha;
break;
case filter_deemph: /* Falls through to high-shelf... */
case filter_highShelf: /* H(s) = A * (A*s^2 + (sqrt(A)/Q)*s + 1)/(s^2 + (sqrt(A)/Q)*s + A) */
if (!A)
return SOX_EFF_NULL;
p->b0 = A*( (A+1) + (A-1)*cos(w0) + 2*sqrt(A)*alpha );
p->b1 = -2*A*( (A-1) + (A+1)*cos(w0) );
p->b2 = A*( (A+1) + (A-1)*cos(w0) - 2*sqrt(A)*alpha );
p->a0 = (A+1) - (A-1)*cos(w0) + 2*sqrt(A)*alpha;
p->a1 = 2*( (A-1) - (A+1)*cos(w0) );
p->a2 = (A+1) - (A-1)*cos(w0) - 2*sqrt(A)*alpha;
break;
case filter_LPF_1: /* single-pole */
p->a1 = -exp(-w0);
p->b0 = 1 + p->a1;
break;
case filter_HPF_1: /* single-pole */
p->a1 = -exp(-w0);
p->b0 = (1 - p->a1)/2;
p->b1 = -p->b0;
break;
case filter_BPF_SPK: case filter_BPF_SPK_N: {
double bw_Hz;
if (!p->width)
p->width = p->fc / 2;
bw_Hz = p->width_type == width_Q? p->fc / p->width :
p->width_type == width_bw_Hz? p->width :
p->fc * (pow(2., p->width) - 1) * pow(2., -0.5 * p->width); /* bw_oct */
#include "band.h" /* Has different licence */
break;
}
case filter_AP1: /* Experimental 1-pole all-pass from Tom Erbe @ UCSD */
p->b0 = exp(-w0);
p->b1 = -1;
p->a1 = -exp(-w0);
break;
case filter_AP2: /* Experimental 2-pole all-pass from Tom Erbe @ UCSD */
p->b0 = 1 - sin(w0);
p->b1 = -2 * cos(w0);
p->b2 = 1 + sin(w0);
p->a0 = 1 + sin(w0);
p->a1 = -2 * cos(w0);
p->a2 = 1 - sin(w0);
break;
case filter_riaa: /* http://www.dsprelated.com/showmessage/73300/3.php */
if (effp->in_signal.rate == 44100) {
static const double zeros[] = {-0.2014898, 0.9233820};
static const double poles[] = {0.7083149, 0.9924091};
make_poly_from_roots(zeros, (size_t)2, &p->b0);
make_poly_from_roots(poles, (size_t)2, &p->a0);
}
else if (effp->in_signal.rate == 48000) {
static const double zeros[] = {-0.1766069, 0.9321590};
static const double poles[] = {0.7396325, 0.9931330};
make_poly_from_roots(zeros, (size_t)2, &p->b0);
make_poly_from_roots(poles, (size_t)2, &p->a0);
}
else if (effp->in_signal.rate == 88200) {
static const double zeros[] = {-0.1168735, 0.9648312};
static const double poles[] = {0.8590646, 0.9964002};
make_poly_from_roots(zeros, (size_t)2, &p->b0);
make_poly_from_roots(poles, (size_t)2, &p->a0);
}
else if (effp->in_signal.rate == 96000) {
static const double zeros[] = {-0.1141486, 0.9676817};
static const double poles[] = {0.8699137, 0.9966946};
make_poly_from_roots(zeros, (size_t)2, &p->b0);
make_poly_from_roots(poles, (size_t)2, &p->a0);
}
else if (effp->in_signal.rate == 192000) {
static const double zeros[] = {-0.1040610965, 0.9837523263};
static const double poles[] = {0.9328992971, 0.9983633125};
make_poly_from_roots(zeros, (size_t)2, &p->b0);
make_poly_from_roots(poles, (size_t)2, &p->a0);
}
else {
lsx_fail("Sample rate must be 44.1k, 48k, 88.2k, 96k, or 192k");
return SOX_EOF;
}
{ /* Normalise to 0dB at 1kHz (Thanks to Glenn Davis) */
double y = 2 * M_PI * 1000 / effp->in_signal.rate;
double b_re = p->b0 + p->b1 * cos(-y) + p->b2 * cos(-2 * y);
double a_re = p->a0 + p->a1 * cos(-y) + p->a2 * cos(-2 * y);
double b_im = p->b1 * sin(-y) + p->b2 * sin(-2 * y);
double a_im = p->a1 * sin(-y) + p->a2 * sin(-2 * y);
double g = 1 / sqrt((sqr(b_re) + sqr(b_im)) / (sqr(a_re) + sqr(a_im)));
p->b0 *= g; p->b1 *= g; p->b2 *= g;
}
mult = (p->b0 + p->b1 + p->b2) / (p->a0 + p->a1 + p->a2);
lsx_debug("gain=%f", linear_to_dB(mult));
break;
}
if (effp->in_signal.mult)
*effp->in_signal.mult /= mult;
return lsx_biquad_start(effp);
}
#define BIQUAD_EFFECT(name,group,usage,flags) \
sox_effect_handler_t const * lsx_##name##_effect_fn(void) { \
static sox_effect_handler_t handler = { \
#name, usage, flags, \
group##_getopts, start, lsx_biquad_flow, 0, 0, 0, sizeof(biquad_t)\
}; \
return &handler; \
}
BIQUAD_EFFECT(highpass, hilo2, "[-1|-2] frequency [width[q|o|h|k](0.707q)]", 0)
BIQUAD_EFFECT(lowpass, hilo2, "[-1|-2] frequency [width[q|o|h|k]](0.707q)", 0)
BIQUAD_EFFECT(bandpass, bandpass, "[-c] frequency width[h|k|q|o]", 0)
BIQUAD_EFFECT(bandreject,bandrej, "frequency width[h|k|q|o]", 0)
BIQUAD_EFFECT(allpass, allpass, "frequency width[h|k|q|o]", 0)
BIQUAD_EFFECT(bass, tone, "gain [frequency(100) [width[s|h|k|q|o]](0.5s)]", 0)
BIQUAD_EFFECT(treble, tone, "gain [frequency(3000) [width[s|h|k|q|o]](0.5s)]", 0)
BIQUAD_EFFECT(equalizer, equalizer,"frequency width[q|o|h|k] gain", 0)
BIQUAD_EFFECT(band, band, "[-n] center [width[h|k|q|o]]", 0)
BIQUAD_EFFECT(deemph, deemph, NULL, 0)
BIQUAD_EFFECT(riaa, riaa, NULL, 0)

@ -1,273 +0,0 @@
#ifndef HAVE_COREAUDIO
/*
* SoX bit-rot detection file; cobbled together
*/
enum {
kAudioHardwarePropertyProcessIsMaster,
kAudioHardwarePropertyIsInitingOrExiting,
kAudioHardwarePropertyDevices,
kAudioHardwarePropertyDefaultInputDevice,
kAudioHardwarePropertyDefaultOutputDevice,
kAudioHardwarePropertyDefaultSystemOutputDevice,
kAudioHardwarePropertyDeviceForUID,
kAudioHardwarePropertySleepingIsAllowed,
kAudioHardwarePropertyUnloadingIsAllowed,
kAudioHardwarePropertyHogModeIsAllowed,
kAudioHardwarePropertyRunLoop,
kAudioHardwarePropertyPlugInForBundleID
};
enum {
kAudioObjectPropertyClass,
kAudioObjectPropertyOwner,
kAudioObjectPropertyCreator,
kAudioObjectPropertyName,
kAudioObjectPropertyManufacturer,
kAudioObjectPropertyElementName,
kAudioObjectPropertyElementCategoryName,
kAudioObjectPropertyElementNumberName,
kAudioObjectPropertyOwnedObjects,
kAudioObjectPropertyListenerAdded,
kAudioObjectPropertyListenerRemoved
};
enum {
kAudioDevicePropertyDeviceName,
kAudioDevicePropertyDeviceNameCFString = kAudioObjectPropertyName,
kAudioDevicePropertyDeviceManufacturer,
kAudioDevicePropertyDeviceManufacturerCFString =
kAudioObjectPropertyManufacturer,
kAudioDevicePropertyRegisterBufferList,
kAudioDevicePropertyBufferSize,
kAudioDevicePropertyBufferSizeRange,
kAudioDevicePropertyChannelName,
kAudioDevicePropertyChannelNameCFString = kAudioObjectPropertyElementName,
kAudioDevicePropertyChannelCategoryName,
kAudioDevicePropertyChannelCategoryNameCFString =
kAudioObjectPropertyElementCategoryName,
kAudioDevicePropertyChannelNumberName,
kAudioDevicePropertyChannelNumberNameCFString =
kAudioObjectPropertyElementNumberName,
kAudioDevicePropertySupportsMixing,
kAudioDevicePropertyStreamFormat,
kAudioDevicePropertyStreamFormats,
kAudioDevicePropertyStreamFormatSupported,
kAudioDevicePropertyStreamFormatMatch,
kAudioDevicePropertyDataSourceNameForID,
kAudioDevicePropertyClockSourceNameForID,
kAudioDevicePropertyPlayThruDestinationNameForID,
kAudioDevicePropertyChannelNominalLineLevelNameForID
};
enum {
kAudioDevicePropertyPlugIn,
kAudioDevicePropertyConfigurationApplication,
kAudioDevicePropertyDeviceUID,
kAudioDevicePropertyModelUID,
kAudioDevicePropertyTransportType,
kAudioDevicePropertyRelatedDevices,
kAudioDevicePropertyClockDomain,
kAudioDevicePropertyDeviceIsAlive,
kAudioDevicePropertyDeviceHasChanged,
kAudioDevicePropertyDeviceIsRunning,
kAudioDevicePropertyDeviceIsRunningSomewhere,
kAudioDevicePropertyDeviceCanBeDefaultDevice,
kAudioDevicePropertyDeviceCanBeDefaultSystemDevice,
kAudioDeviceProcessorOverload,
kAudioDevicePropertyHogMode,
kAudioDevicePropertyLatency,
kAudioDevicePropertyBufferFrameSize,
kAudioDevicePropertyBufferFrameSizeRange,
kAudioDevicePropertyUsesVariableBufferFrameSizes,
kAudioDevicePropertyStreams,
kAudioDevicePropertySafetyOffset,
kAudioDevicePropertyIOCycleUsage,
kAudioDevicePropertyStreamConfiguration,
kAudioDevicePropertyIOProcStreamUsage,
kAudioDevicePropertyPreferredChannelsForStereo,
kAudioDevicePropertyPreferredChannelLayout,
kAudioDevicePropertyNominalSampleRate,
kAudioDevicePropertyAvailableNominalSampleRates,
kAudioDevicePropertyActualSampleRate
};
enum {
kAudioFormatLinearPCM,
kAudioFormatAC3,
kAudioFormat60958AC3,
kAudioFormatAppleIMA4,
kAudioFormatMPEG4AAC,
kAudioFormatMPEG4CELP,
kAudioFormatMPEG4HVXC,
kAudioFormatMPEG4TwinVQ,
kAudioFormatMACE3,
kAudioFormatMACE6,
kAudioFormatULaw,
kAudioFormatALaw,
kAudioFormatQDesign,
kAudioFormatQDesign2,
kAudioFormatQUALCOMM,
kAudioFormatMPEGLayer1,
kAudioFormatMPEGLayer2,
kAudioFormatMPEGLayer3,
kAudioFormatDVAudio,
kAudioFormatVariableDurationDVAudio,
kAudioFormatTimeCode,
kAudioFormatMIDIStream,
kAudioFormatParameterValueStream,
kAudioFormatAppleLossless
};
enum {
kAudioFormatFlagIsFloat = (1L << 0),
kAudioFormatFlagIsBigEndian = (1L << 1),
kAudioFormatFlagIsSignedInteger = (1L << 2),
kAudioFormatFlagIsPacked = (1L << 3),
kAudioFormatFlagIsAlignedHigh = (1L << 4),
kAudioFormatFlagIsNonInterleaved = (1L << 5),
kAudioFormatFlagIsNonMixable = (1L << 6),
kLinearPCMFormatFlagIsFloat = kAudioFormatFlagIsFloat,
kLinearPCMFormatFlagIsBigEndian = kAudioFormatFlagIsBigEndian,
kLinearPCMFormatFlagIsSignedInteger = kAudioFormatFlagIsSignedInteger,
kLinearPCMFormatFlagIsPacked = kAudioFormatFlagIsPacked,
kLinearPCMFormatFlagIsAlignedHigh = kAudioFormatFlagIsAlignedHigh,
kLinearPCMFormatFlagIsNonInterleaved = kAudioFormatFlagIsNonInterleaved,
kLinearPCMFormatFlagIsNonMixable = kAudioFormatFlagIsNonMixable,
kAppleLosslessFormatFlag_16BitSourceData = 1,
kAppleLosslessFormatFlag_20BitSourceData = 2,
kAppleLosslessFormatFlag_24BitSourceData = 3,
kAppleLosslessFormatFlag_32BitSourceData = 4
};
enum {
kAudioFormatFlagsNativeEndian = kAudioFormatFlagIsBigEndian,
kAudioFormatFlagsNativeFloatPacked =
kAudioFormatFlagIsFloat | kAudioFormatFlagsNativeEndian |
kAudioFormatFlagIsPacked
};
enum {
kAudioDeviceUnknown
};
enum {
kVariableLengthArray = 1
};
enum {
kAudioHardwareNoError = 0,
noErr = kAudioHardwareNoError
};
enum {
false
};
typedef double Float64;
typedef float Float32;
typedef int SInt32;
typedef int Boolean;
typedef int OSErr;
typedef short SInt16;
typedef unsigned int UInt32;
typedef unsigned long int UInt64;
typedef SInt32 OSStatus;
typedef UInt32 AudioObjectID;
typedef UInt32 AudioHardwarePropertyID;
typedef UInt32 AudioDevicePropertyID;
typedef AudioObjectID AudioDeviceID;
struct AudioStreamBasicDescription {
Float64 mSampleRate;
UInt32 mFormatID;
UInt32 mFormatFlags;
UInt32 mBytesPerPacket;
UInt32 mFramesPerPacket;
UInt32 mBytesPerFrame;
UInt32 mChannelsPerFrame;
UInt32 mBitsPerChannel;
UInt32 mReserved;
};
typedef struct AudioStreamBasicDescription AudioStreamBasicDescription;
struct SMPTETime {
SInt16 mSubframes;
SInt16 mSubframeDivisor;
UInt32 mCounter;
UInt32 mType;
UInt32 mFlags;
SInt16 mHours;
SInt16 mMinutes;
SInt16 mSeconds;
SInt16 mFrames;
};
typedef struct SMPTETime SMPTETime;
struct AudioTimeStamp {
Float64 mSampleTime;
UInt64 mHostTime;
Float64 mRateScalar;
UInt64 mWordClockTime;
SMPTETime mSMPTETime;
UInt32 mFlags;
UInt32 mReserved;
};
typedef struct AudioTimeStamp AudioTimeStamp;
struct AudioBuffer {
UInt32 mNumberChannels;
UInt32 mDataByteSize;
void *mData;
};
typedef struct AudioBuffer AudioBuffer;
struct AudioBufferList {
UInt32 mNumberBuffers;
AudioBuffer mBuffers[kVariableLengthArray];
};
typedef struct AudioBufferList AudioBufferList;
typedef OSStatus(*AudioDeviceIOProc) (AudioDeviceID inDevice,
const AudioTimeStamp * inNow,
const AudioBufferList * inInputData,
const AudioTimeStamp * inInputTime,
AudioBufferList * outOutputData,
const AudioTimeStamp * inOutputTime,
void *inClientData);
OSStatus AudioHardwareGetProperty(AudioHardwarePropertyID inPropertyID,
UInt32 * ioPropertyDataSize,
void *outPropertyData);
OSStatus AudioHardwareGetPropertyInfo(AudioHardwarePropertyID inPropertyID,
UInt32 * ioPropertyDataSize,
void *outPropertyData);
OSStatus AudioDeviceSetProperty(AudioDeviceID inDevice,
const AudioTimeStamp * inWhen,
UInt32 inChannel, Boolean isInput,
AudioDevicePropertyID inPropertyID,
UInt32 inPropertyDataSize,
const void *inPropertyData);
OSStatus AudioDeviceGetProperty(AudioDeviceID inDevice, UInt32 inChannel,
Boolean isInput,
AudioDevicePropertyID inPropertyID,
UInt32 * ioPropertyDataSize,
void *outPropertyData);
OSStatus AudioDeviceAddIOProc(AudioDeviceID inDevice,
AudioDeviceIOProc inProc, void *inClientData);
OSStatus AudioDeviceStart(AudioDeviceID inDevice, AudioDeviceIOProc inProc);
OSStatus AudioDeviceStop(AudioDeviceID inDevice, AudioDeviceIOProc inProc);
#endif

@ -1,35 +0,0 @@
/* libSoX file format: CAF 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"
LSX_FORMAT_HANDLER(caf)
{
static char const * const names[] = {"caf", NULL};
static unsigned const write_encodings[] = {
SOX_ENCODING_SIGN2, 16, 24, 32, 8, 0,
SOX_ENCODING_FLOAT, 32, 64, 0,
SOX_ENCODING_ALAW, 8, 0,
SOX_ENCODING_ULAW, 8, 0,
0};
static sox_format_handler_t handler;
handler = *lsx_sndfile_format_fn();
handler.description = "Apples's Core Audio Format";
handler.names = names;
handler.write_formats = write_encodings;
return &handler;
}

@ -1,351 +0,0 @@
/* 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.
*/
/*
* Chorus effect.
*
* Flow diagram scheme for n delays ( 1 <= n <= MAX_CHORUS ):
*
* * gain-in ___
* ibuff -----+--------------------------------------------->| |
* | _________ | |
* | | | * decay 1 | |
* +---->| delay 1 |----------------------------->| |
* | |_________| | |
* | /|\ | |
* : | | |
* : +-----------------+ +--------------+ | + |
* : | Delay control 1 |<--| mod. speed 1 | | |
* : +-----------------+ +--------------+ | |
* | _________ | |
* | | | * decay n | |
* +---->| delay n |----------------------------->| |
* |_________| | |
* /|\ |___|
* | |
* +-----------------+ +--------------+ | * gain-out
* | Delay control n |<--| mod. speed n | |
* +-----------------+ +--------------+ +----->obuff
*
*
* The delay i is controled by a sine or triangle modulation i ( 1 <= i <= n).
*
* Usage:
* chorus gain-in gain-out delay-1 decay-1 speed-1 depth-1 -s1|t1 [
* delay-2 decay-2 speed-2 depth-2 -s2|-t2 ... ]
*
* Where:
* gain-in, decay-1 ... decay-n : 0.0 ... 1.0 volume
* gain-out : 0.0 ... volume
* delay-1 ... delay-n : 20.0 ... 100.0 msec
* speed-1 ... speed-n : 0.1 ... 5.0 Hz modulation 1 ... n
* depth-1 ... depth-n : 0.0 ... 10.0 msec modulated delay 1 ... n
* -s1 ... -sn : modulation by sine 1 ... n
* -t1 ... -tn : modulation by triangle 1 ... n
*
* 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 )
*
*/
/*
* libSoX chorus effect file.
*/
#include "sox_i.h"
#include <stdlib.h> /* Harmless, and prototypes atof() etc. --dgc */
#include <string.h>
#define MOD_SINE 0
#define MOD_TRIANGLE 1
#define MAX_CHORUS 7
typedef struct {
int num_chorus;
int modulation[MAX_CHORUS];
int counter;
long phase[MAX_CHORUS];
float *chorusbuf;
float in_gain, out_gain;
float delay[MAX_CHORUS], decay[MAX_CHORUS];
float speed[MAX_CHORUS], depth[MAX_CHORUS];
long length[MAX_CHORUS];
int *lookup_tab[MAX_CHORUS];
int depth_samples[MAX_CHORUS], samples[MAX_CHORUS];
int maxsamples;
unsigned int fade_out;
} priv_t;
/*
* Process options
*/
static int sox_chorus_getopts(sox_effect_t * effp, int argc, char **argv)
{
priv_t * chorus = (priv_t *) effp->priv;
int i;
--argc, ++argv;
chorus->num_chorus = 0;
i = 0;
if ( ( argc < 7 ) || (( argc - 2 ) % 5 ) )
return lsx_usage(effp);
sscanf(argv[i++], "%f", &chorus->in_gain);
sscanf(argv[i++], "%f", &chorus->out_gain);
while ( i < argc ) {
if ( chorus->num_chorus > MAX_CHORUS )
{
lsx_fail("chorus: to many delays, use less than %i delays", MAX_CHORUS);
return (SOX_EOF);
}
sscanf(argv[i++], "%f", &chorus->delay[chorus->num_chorus]);
sscanf(argv[i++], "%f", &chorus->decay[chorus->num_chorus]);
sscanf(argv[i++], "%f", &chorus->speed[chorus->num_chorus]);
sscanf(argv[i++], "%f", &chorus->depth[chorus->num_chorus]);
if ( !strcmp(argv[i], "-s"))
chorus->modulation[chorus->num_chorus] = MOD_SINE;
else if ( ! strcmp(argv[i], "-t"))
chorus->modulation[chorus->num_chorus] = MOD_TRIANGLE;
else
return lsx_usage(effp);
i++;
chorus->num_chorus++;
}
return (SOX_SUCCESS);
}
/*
* Prepare for processing.
*/
static int sox_chorus_start(sox_effect_t * effp)
{
priv_t * chorus = (priv_t *) effp->priv;
int i;
float sum_in_volume;
chorus->maxsamples = 0;
if ( chorus->in_gain < 0.0 )
{
lsx_fail("chorus: gain-in must be positive!");
return (SOX_EOF);
}
if ( chorus->in_gain > 1.0 )
{
lsx_fail("chorus: gain-in must be less than 1.0!");
return (SOX_EOF);
}
if ( chorus->out_gain < 0.0 )
{
lsx_fail("chorus: gain-out must be positive!");
return (SOX_EOF);
}
for ( i = 0; i < chorus->num_chorus; i++ ) {
chorus->samples[i] = (int) ( ( chorus->delay[i] +
chorus->depth[i] ) * effp->in_signal.rate / 1000.0);
chorus->depth_samples[i] = (int) (chorus->depth[i] *
effp->in_signal.rate / 1000.0);
if ( chorus->delay[i] < 20.0 )
{
lsx_fail("chorus: delay must be more than 20.0 msec!");
return (SOX_EOF);
}
if ( chorus->delay[i] > 100.0 )
{
lsx_fail("chorus: delay must be less than 100.0 msec!");
return (SOX_EOF);
}
if ( chorus->speed[i] < 0.1 )
{
lsx_fail("chorus: speed must be more than 0.1 Hz!");
return (SOX_EOF);
}
if ( chorus->speed[i] > 5.0 )
{
lsx_fail("chorus: speed must be less than 5.0 Hz!");
return (SOX_EOF);
}
if ( chorus->depth[i] < 0.0 )
{
lsx_fail("chorus: delay must be more positive!");
return (SOX_EOF);
}
if ( chorus->depth[i] > 10.0 )
{
lsx_fail("chorus: delay must be less than 10.0 msec!");
return (SOX_EOF);
}
if ( chorus->decay[i] < 0.0 )
{
lsx_fail("chorus: decay must be positive!" );
return (SOX_EOF);
}
if ( chorus->decay[i] > 1.0 )
{
lsx_fail("chorus: decay must be less that 1.0!" );
return (SOX_EOF);
}
chorus->length[i] = effp->in_signal.rate / chorus->speed[i];
chorus->lookup_tab[i] = lsx_malloc(sizeof (int) * chorus->length[i]);
if (chorus->modulation[i] == MOD_SINE)
lsx_generate_wave_table(SOX_WAVE_SINE, SOX_INT, chorus->lookup_tab[i],
(size_t)chorus->length[i], 0., (double)chorus->depth_samples[i], 0.);
else
lsx_generate_wave_table(SOX_WAVE_TRIANGLE, SOX_INT, chorus->lookup_tab[i],
(size_t)chorus->length[i],
(double)(chorus->samples[i] - 1 - 2 * chorus->depth_samples[i]),
(double)(chorus->samples[i] - 1), 3 * M_PI_2);
chorus->phase[i] = 0;
if ( chorus->samples[i] > chorus->maxsamples )
chorus->maxsamples = chorus->samples[i];
}
/* Be nice and check the hint with warning, if... */
sum_in_volume = 1.0;
for ( i = 0; i < chorus->num_chorus; i++ )
sum_in_volume += chorus->decay[i];
if ( chorus->in_gain * ( sum_in_volume ) > 1.0 / chorus->out_gain )
lsx_warn("chorus: warning >>> gain-out can cause saturation or clipping of output <<<");
chorus->chorusbuf = lsx_malloc(sizeof (float) * chorus->maxsamples);
for ( i = 0; i < chorus->maxsamples; i++ )
chorus->chorusbuf[i] = 0.0;
chorus->counter = 0;
chorus->fade_out = chorus->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_chorus_flow(sox_effect_t * effp, const sox_sample_t *ibuf, sox_sample_t *obuf,
size_t *isamp, size_t *osamp)
{
priv_t * chorus = (priv_t *) effp->priv;
int i;
float 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 = (float) *ibuf++ / 256;
/* Compute output first */
d_out = d_in * chorus->in_gain;
for ( i = 0; i < chorus->num_chorus; i++ )
d_out += chorus->chorusbuf[(chorus->maxsamples +
chorus->counter - chorus->lookup_tab[i][chorus->phase[i]]) %
chorus->maxsamples] * chorus->decay[i];
/* Adjust the output volume and size to 24 bit */
d_out = d_out * chorus->out_gain;
out = SOX_24BIT_CLIP_COUNT((sox_sample_t) d_out, effp->clips);
*obuf++ = out * 256;
/* Mix decay of delay and input */
chorus->chorusbuf[chorus->counter] = d_in;
chorus->counter =
( chorus->counter + 1 ) % chorus->maxsamples;
for ( i = 0; i < chorus->num_chorus; i++ )
chorus->phase[i] =
( chorus->phase[i] + 1 ) % chorus->length[i];
}
/* processed all samples */
return (SOX_SUCCESS);
}
/*
* Drain out reverb lines.
*/
static int sox_chorus_drain(sox_effect_t * effp, sox_sample_t *obuf, size_t *osamp)
{
priv_t * chorus = (priv_t *) effp->priv;
size_t done;
int i;
float d_in, d_out;
sox_sample_t out;
done = 0;
while ( ( done < *osamp ) && ( done < chorus->fade_out ) ) {
d_in = 0;
d_out = 0;
/* Compute output first */
for ( i = 0; i < chorus->num_chorus; i++ )
d_out += chorus->chorusbuf[(chorus->maxsamples +
chorus->counter - chorus->lookup_tab[i][chorus->phase[i]]) %
chorus->maxsamples] * chorus->decay[i];
/* Adjust the output volume and size to 24 bit */
d_out = d_out * chorus->out_gain;
out = SOX_24BIT_CLIP_COUNT((sox_sample_t) d_out, effp->clips);
*obuf++ = out * 256;
/* Mix decay of delay and input */
chorus->chorusbuf[chorus->counter] = d_in;
chorus->counter =
( chorus->counter + 1 ) % chorus->maxsamples;
for ( i = 0; i < chorus->num_chorus; i++ )
chorus->phase[i] =
( chorus->phase[i] + 1 ) % chorus->length[i];
done++;
chorus->fade_out--;
}
/* samples played, it remains */
*osamp = done;
if (chorus->fade_out == 0)
return SOX_EOF;
else
return SOX_SUCCESS;
}
/*
* Clean up chorus effect.
*/
static int sox_chorus_stop(sox_effect_t * effp)
{
priv_t * chorus = (priv_t *) effp->priv;
int i;
free(chorus->chorusbuf);
chorus->chorusbuf = NULL;
for ( i = 0; i < chorus->num_chorus; i++ ) {
free(chorus->lookup_tab[i]);
chorus->lookup_tab[i] = NULL;
}
return (SOX_SUCCESS);
}
static sox_effect_handler_t sox_chorus_effect = {
"chorus",
"gain-in gain-out delay decay speed depth [ -s | -t ]",
SOX_EFF_LENGTH | SOX_EFF_GAIN,
sox_chorus_getopts,
sox_chorus_start,
sox_chorus_flow,
sox_chorus_drain,
sox_chorus_stop,
NULL, sizeof(priv_t)
};
const sox_effect_handler_t *lsx_chorus_effect_fn(void)
{
return &sox_chorus_effect;
}

@ -1,293 +0,0 @@
/* libSoX compander effect
*
* Written by Nick Bailey (nick@bailey-family.org.uk or
* n.bailey@elec.gla.ac.uk)
*
* Copyright 1999 Chris Bagwell And Nick Bailey
* This source code is freely redistributable and may be used for
* any purpose. This copyright notice must be maintained.
* Chris Bagwell And Nick Bailey are not responsible for
* the consequences of using this software.
*/
#include "sox_i.h"
#include <string.h>
#include <stdlib.h>
#include "compandt.h"
/*
* Compressor/expander effect for libSoX.
*
* Flow diagram for one channel:
*
* ------------ ---------------
* | | | | ---
* ibuff ---+---| integrator |--->| transfer func |--->| |
* | | | | | | |
* | ------------ --------------- | | * gain
* | | * |----------->obuff
* | ------- | |
* | | | | |
* +----->| delay |-------------------------->| |
* | | ---
* -------
*/
#define compand_usage \
"attack1,decay1{,attack2,decay2} [soft-knee-dB:]in-dB1[,out-dB1]{,in-dB2,out-dB2} [gain [initial-volume-dB [delay]]]\n" \
"\twhere {} means optional and repeatable and [] means optional.\n" \
"\tdB values are floating point or -inf'; times are in seconds."
/*
* Note: clipping can occur if the transfer function pushes things too
* close to 0 dB. In that case, use a negative gain, or reduce the
* output level of the transfer function.
*/
typedef struct {
sox_compandt_t transfer_fn;
struct {
double attack_times[2]; /* 0:attack_time, 1:decay_time */
double volume; /* Current "volume" of each channel */
} * channels;
unsigned expectedChannels;/* Also flags that channels aren't to be treated
individually when = 1 and input not mono */
double delay; /* Delay to apply before companding */
sox_sample_t *delay_buf; /* Old samples, used for delay processing */
ptrdiff_t delay_buf_size;/* Size of delay_buf in samples */
ptrdiff_t delay_buf_index; /* Index into delay_buf */
ptrdiff_t delay_buf_cnt; /* No. of active entries in delay_buf */
int delay_buf_full; /* Shows buffer situation (important for drain) */
char *arg0; /* copies of arguments, so that they may be modified */
char *arg1;
char *arg2;
} priv_t;
static int getopts(sox_effect_t * effp, int argc, char * * argv)
{
priv_t * l = (priv_t *) effp->priv;
char * s;
char dummy; /* To check for extraneous chars. */
unsigned pairs, i, j, commas;
--argc, ++argv;
if (argc < 2 || argc > 5)
return lsx_usage(effp);
l->arg0 = lsx_strdup(argv[0]);
l->arg1 = lsx_strdup(argv[1]);
l->arg2 = argc > 2 ? lsx_strdup(argv[2]) : NULL;
/* Start by checking the attack and decay rates */
for (s = l->arg0, commas = 0; *s; ++s) if (*s == ',') ++commas;
if ((commas % 2) == 0) {
lsx_fail("there must be an even number of attack/decay parameters");
return SOX_EOF;
}
pairs = 1 + commas/2;
l->channels = lsx_calloc(pairs, sizeof(*l->channels));
l->expectedChannels = pairs;
/* Now tokenise the rates string and set up these arrays. Keep
them in seconds at the moment: we don't know the sample rate yet. */
for (i = 0, s = strtok(l->arg0, ","); s != NULL; ++i) {
for (j = 0; j < 2; ++j) {
if (sscanf(s, "%lf %c", &l->channels[i].attack_times[j], &dummy) != 1) {
lsx_fail("syntax error trying to read attack/decay time");
return SOX_EOF;
} else if (l->channels[i].attack_times[j] < 0) {
lsx_fail("attack & decay times can't be less than 0 seconds");
return SOX_EOF;
}
s = strtok(NULL, ",");
}
}
if (!lsx_compandt_parse(&l->transfer_fn, l->arg1, l->arg2))
return SOX_EOF;
/* Set the initial "volume" to be attibuted to the input channels.
Unless specified, choose 0dB otherwise clipping will
result if the user has seleced a long attack time */
for (i = 0; i < l->expectedChannels; ++i) {
double init_vol_dB = 0;
if (argc > 3 && sscanf(argv[3], "%lf %c", &init_vol_dB, &dummy) != 1) {
lsx_fail("syntax error trying to read initial volume");
return SOX_EOF;
} else if (init_vol_dB > 0) {
lsx_fail("initial volume is relative to maximum volume so can't exceed 0dB");
return SOX_EOF;
}
l->channels[i].volume = pow(10., init_vol_dB / 20);
}
/* If there is a delay, store it. */
if (argc > 4 && sscanf(argv[4], "%lf %c", &l->delay, &dummy) != 1) {
lsx_fail("syntax error trying to read delay value");
return SOX_EOF;
} else if (l->delay < 0) {
lsx_fail("delay can't be less than 0 seconds");
return SOX_EOF;
}
return SOX_SUCCESS;
}
static int start(sox_effect_t * effp)
{
priv_t * l = (priv_t *) effp->priv;
unsigned i, j;
lsx_debug("%i input channel(s) expected: actually %i",
l->expectedChannels, effp->out_signal.channels);
for (i = 0; i < l->expectedChannels; ++i)
lsx_debug("Channel %i: attack = %g decay = %g", i,
l->channels[i].attack_times[0], l->channels[i].attack_times[1]);
if (!lsx_compandt_show(&l->transfer_fn, effp->global_info->plot))
return SOX_EOF;
/* Convert attack and decay rates using number of samples */
for (i = 0; i < l->expectedChannels; ++i)
for (j = 0; j < 2; ++j)
if (l->channels[i].attack_times[j] > 1.0/effp->out_signal.rate)
l->channels[i].attack_times[j] = 1.0 -
exp(-1.0/(effp->out_signal.rate * l->channels[i].attack_times[j]));
else
l->channels[i].attack_times[j] = 1.0;
/* Allocate the delay buffer */
l->delay_buf_size = l->delay * effp->out_signal.rate * effp->out_signal.channels;
if (l->delay_buf_size > 0)
l->delay_buf = lsx_calloc((size_t)l->delay_buf_size, sizeof(*l->delay_buf));
l->delay_buf_index = 0;
l->delay_buf_cnt = 0;
l->delay_buf_full= 0;
return SOX_SUCCESS;
}
/*
* Update a volume value using the given sample
* value, the attack rate and decay rate
*/
static void doVolume(double *v, double samp, priv_t * l, int chan)
{
double s = -samp / SOX_SAMPLE_MIN;
double delta = s - *v;
if (delta > 0.0) /* increase volume according to attack rate */
*v += delta * l->channels[chan].attack_times[0];
else /* reduce volume according to decay rate */
*v += delta * l->channels[chan].attack_times[1];
}
static int flow(sox_effect_t * effp, const sox_sample_t *ibuf, sox_sample_t *obuf,
size_t *isamp, size_t *osamp)
{
priv_t * l = (priv_t *) effp->priv;
int len = (*isamp > *osamp) ? *osamp : *isamp;
int filechans = effp->out_signal.channels;
int idone,odone;
for (idone = 0,odone = 0; idone < len; ibuf += filechans) {
int chan;
/* Maintain the volume fields by simulating a leaky pump circuit */
for (chan = 0; chan < filechans; ++chan) {
if (l->expectedChannels == 1 && filechans > 1) {
/* User is expecting same compander for all channels */
int i;
double maxsamp = 0.0;
for (i = 0; i < filechans; ++i) {
double rect = fabs((double)ibuf[i]);
if (rect > maxsamp) maxsamp = rect;
}
doVolume(&l->channels[0].volume, maxsamp, l, 0);
break;
} else
doVolume(&l->channels[chan].volume, fabs((double)ibuf[chan]), l, chan);
}
/* Volume memory is updated: perform compand */
for (chan = 0; chan < filechans; ++chan) {
int ch = l->expectedChannels > 1 ? chan : 0;
double level_in_lin = l->channels[ch].volume;
double level_out_lin = lsx_compandt(&l->transfer_fn, level_in_lin);
double checkbuf;
if (l->delay_buf_size <= 0) {
checkbuf = ibuf[chan] * level_out_lin;
SOX_SAMPLE_CLIP_COUNT(checkbuf, effp->clips);
obuf[odone++] = checkbuf;
idone++;
} else {
if (l->delay_buf_cnt >= l->delay_buf_size) {
l->delay_buf_full=1; /* delay buffer is now definitely full */
checkbuf = l->delay_buf[l->delay_buf_index] * level_out_lin;
SOX_SAMPLE_CLIP_COUNT(checkbuf, effp->clips);
obuf[odone] = checkbuf;
odone++;
idone++;
} else {
l->delay_buf_cnt++;
idone++; /* no "odone++" because we did not fill obuf[...] */
}
l->delay_buf[l->delay_buf_index++] = ibuf[chan];
l->delay_buf_index %= l->delay_buf_size;
}
}
}
*isamp = idone; *osamp = odone;
return (SOX_SUCCESS);
}
static int drain(sox_effect_t * effp, sox_sample_t *obuf, size_t *osamp)
{
priv_t * l = (priv_t *) effp->priv;
size_t chan, done = 0;
if (l->delay_buf_full == 0)
l->delay_buf_index = 0;
while (done+effp->out_signal.channels <= *osamp && l->delay_buf_cnt > 0)
for (chan = 0; chan < effp->out_signal.channels; ++chan) {
int c = l->expectedChannels > 1 ? chan : 0;
double level_in_lin = l->channels[c].volume;
double level_out_lin = lsx_compandt(&l->transfer_fn, level_in_lin);
obuf[done++] = l->delay_buf[l->delay_buf_index++] * level_out_lin;
l->delay_buf_index %= l->delay_buf_size;
l->delay_buf_cnt--;
}
*osamp = done;
return l->delay_buf_cnt > 0 ? SOX_SUCCESS : SOX_EOF;
}
static int stop(sox_effect_t * effp)
{
priv_t * l = (priv_t *) effp->priv;
free(l->delay_buf);
return SOX_SUCCESS;
}
static int lsx_kill(sox_effect_t * effp)
{
priv_t * l = (priv_t *) effp->priv;
lsx_compandt_kill(&l->transfer_fn);
free(l->channels);
free(l->arg0);
free(l->arg1);
free(l->arg2);
return SOX_SUCCESS;
}
sox_effect_handler_t const * lsx_compand_effect_fn(void)
{
static sox_effect_handler_t handler = {
"compand", compand_usage, SOX_EFF_MCHAN | SOX_EFF_GAIN,
getopts, start, flow, drain, stop, lsx_kill, sizeof(priv_t)
};
return &handler;
}

@ -1,229 +0,0 @@
/* libSoX Compander Transfer Function: (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
*/
#include "sox_i.h"
#include "compandt.h"
#include <string.h>
#define LOG_TO_LOG10(x) ((x) * 20 / M_LN10)
sox_bool lsx_compandt_show(sox_compandt_t * t, sox_plot_t plot)
{
int i;
for (i = 1; t->segments[i-1].x; ++i)
lsx_debug("TF: %g %g %g %g",
LOG_TO_LOG10(t->segments[i].x),
LOG_TO_LOG10(t->segments[i].y),
LOG_TO_LOG10(t->segments[i].a),
LOG_TO_LOG10(t->segments[i].b));
if (plot == sox_plot_octave) {
printf(
"%% GNU Octave file (may also work with MATLAB(R) )\n"
"in=linspace(-99.5,0,200);\n"
"out=[");
for (i = -199; i <= 0; ++i) {
double in = i/2.;
double in_lin = pow(10., in/20);
printf("%g ", in + 20 * log10(lsx_compandt(t, in_lin)));
}
printf(
"];\n"
"plot(in,out)\n"
"title('SoX effect: compand')\n"
"xlabel('Input level (dB)')\n"
"ylabel('Output level (dB)')\n"
"grid on\n"
"disp('Hit return to continue')\n"
"pause\n");
return sox_false;
}
if (plot == sox_plot_gnuplot) {
printf(
"# gnuplot file\n"
"set title 'SoX effect: compand'\n"
"set xlabel 'Input level (dB)'\n"
"set ylabel 'Output level (dB)'\n"
"set grid xtics ytics\n"
"set key off\n"
"plot '-' with lines\n");
for (i = -199; i <= 0; ++i) {
double in = i/2.;
double in_lin = pow(10., in/20);
printf("%g %g\n", in, in + 20 * log10(lsx_compandt(t, in_lin)));
}
printf(
"e\n"
"pause -1 'Hit return to continue'\n");
return sox_false;
}
return sox_true;
}
static void prepare_transfer_fn(sox_compandt_t * t)
{
int i;
double radius = t->curve_dB * M_LN10 / 20;
for (i = 0; !i || t->segments[i-2].x; i += 2) {
t->segments[i].y += t->outgain_dB;
t->segments[i].x *= M_LN10 / 20; /* Convert to natural logs */
t->segments[i].y *= M_LN10 / 20;
}
#define line1 t->segments[i - 4]
#define curve t->segments[i - 3]
#define line2 t->segments[i - 2]
#define line3 t->segments[i - 0]
for (i = 4; t->segments[i - 2].x; i += 2) {
double x, y, cx, cy, in1, in2, out1, out2, theta, len, r;
line1.a = 0;
line1.b = (line2.y - line1.y) / (line2.x - line1.x);
line2.a = 0;
line2.b = (line3.y - line2.y) / (line3.x - line2.x);
theta = atan2(line2.y - line1.y, line2.x - line1.x);
len = sqrt(pow(line2.x - line1.x, 2.) + pow(line2.y - line1.y, 2.));
r = min(radius, len);
curve.x = line2.x - r * cos(theta);
curve.y = line2.y - r * sin(theta);
theta = atan2(line3.y - line2.y, line3.x - line2.x);
len = sqrt(pow(line3.x - line2.x, 2.) + pow(line3.y - line2.y, 2.));
r = min(radius, len / 2);
x = line2.x + r * cos(theta);
y = line2.y + r * sin(theta);
cx = (curve.x + line2.x + x) / 3;
cy = (curve.y + line2.y + y) / 3;
line2.x = x;
line2.y = y;
in1 = cx - curve.x;
out1 = cy - curve.y;
in2 = line2.x - curve.x;
out2 = line2.y - curve.y;
curve.a = (out2/in2 - out1/in1) / (in2-in1);
curve.b = out1/in1 - curve.a*in1;
}
#undef line1
#undef curve
#undef line2
#undef line3
t->segments[i - 3].x = 0;
t->segments[i - 3].y = t->segments[i - 2].y;
t->in_min_lin = exp(t->segments[1].x);
t->out_min_lin= exp(t->segments[1].y);
}
static sox_bool parse_transfer_value(char const * text, double * value)
{
char dummy; /* To check for extraneous chars. */
if (!text) {
lsx_fail("syntax error trying to read transfer function value");
return sox_false;
}
if (!strcmp(text, "-inf"))
*value = -20 * log10(-(double)SOX_SAMPLE_MIN);
else if (sscanf(text, "%lf %c", value, &dummy) != 1) {
lsx_fail("syntax error trying to read transfer function value");
return sox_false;
}
else if (*value > 0) {
lsx_fail("transfer function values are relative to maximum volume so can't exceed 0dB");
return sox_false;
}
return sox_true;
}
sox_bool lsx_compandt_parse(sox_compandt_t * t, char * points, char * gain)
{
char const * text = points;
unsigned i, j, num, pairs, commas = 0;
char dummy; /* To check for extraneous chars. */
if (sscanf(points, "%lf %c", &t->curve_dB, &dummy) == 2 && dummy == ':')
points = strchr(points, ':') + 1;
else t->curve_dB = 0;
t->curve_dB = max(t->curve_dB, .01);
while (*text) commas += *text++ == ',';
pairs = 1 + commas / 2;
++pairs; /* allow room for extra pair at the beginning */
pairs *= 2; /* allow room for the auto-curves */
++pairs; /* allow room for 0,0 at end */
t->segments = lsx_calloc(pairs, sizeof(*t->segments));
#define s(n) t->segments[2*((n)+1)]
for (i = 0, text = strtok(points, ","); text != NULL; ++i) {
if (!parse_transfer_value(text, &s(i).x))
return sox_false;
if (i && s(i-1).x > s(i).x) {
lsx_fail("transfer function input values must be strictly increasing");
return sox_false;
}
if (i || (commas & 1)) {
text = strtok(NULL, ",");
if (!parse_transfer_value(text, &s(i).y))
return sox_false;
s(i).y -= s(i).x;
}
text = strtok(NULL, ",");
}
num = i;
if (num == 0 || s(num-1).x) /* Add 0,0 if necessary */
++num;
#undef s
if (gain && sscanf(gain, "%lf %c", &t->outgain_dB, &dummy) != 1) {
lsx_fail("syntax error trying to read post-processing gain value");
return sox_false;
}
#define s(n) t->segments[2*(n)]
s(0).x = s(1).x - 2 * t->curve_dB; /* Add a tail off segment at the start */
s(0).y = s(1).y;
++num;
for (i = 2; i < num; ++i) { /* Join adjacent colinear segments */
double g1 = (s(i-1).y - s(i-2).y) * (s(i-0).x - s(i-1).x);
double g2 = (s(i-0).y - s(i-1).y) * (s(i-1).x - s(i-2).x);
if (fabs(g1 - g2)) /* fabs stops epsilon problems */
continue;
--num;
for (j = --i; j < num; ++j)
s(j) = s(j+1);
}
#undef s
prepare_transfer_fn(t);
return sox_true;
}
void lsx_compandt_kill(sox_compandt_t * p)
{
free(p->segments);
}

@ -1,52 +0,0 @@
/* libSoX Compander Transfer Function (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
*/
#include <math.h>
typedef struct {
struct sox_compandt_segment {
double x, y; /* 1st point in segment */
double a, b; /* Quadratic coeffecients for rest of segment */
} * segments;
double in_min_lin;
double out_min_lin;
double outgain_dB; /* Post processor gain */
double curve_dB;
} sox_compandt_t;
sox_bool lsx_compandt_parse(sox_compandt_t * t, char * points, char * gain);
sox_bool lsx_compandt_show(sox_compandt_t * t, sox_plot_t plot);
void lsx_compandt_kill(sox_compandt_t * p);
/* Place in header to allow in-lining */
static double lsx_compandt(sox_compandt_t * t, double in_lin)
{
struct sox_compandt_segment * s;
double in_log, out_log;
if (in_lin <= t->in_min_lin)
return t->out_min_lin;
in_log = log(in_lin);
for (s = t->segments + 1; in_log > s[1].x; ++s);
in_log -= s->x;
out_log = s->y + in_log * (s->a * in_log + s->b);
return exp(out_log);
}

@ -1,49 +0,0 @@
/* libSoX effect: Contrast Enhancement (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 {double contrast;} priv_t;
static int create(sox_effect_t * effp, int argc, char * * argv)
{
priv_t * p = (priv_t *)effp->priv;
p->contrast = 75;
--argc, ++argv;
do {NUMERIC_PARAMETER(contrast, 0, 100)} while (0);
p->contrast /= 750; /* shift range to 0 to 0.1333, default 0.1 */
return argc? lsx_usage(effp) : 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);
while (len--) {
double d = *ibuf++ * (-M_PI_2 / SOX_SAMPLE_MIN);
*obuf++ = sin(d + p->contrast * sin(d * 4)) * SOX_SAMPLE_MAX;
}
return SOX_SUCCESS;
}
sox_effect_handler_t const * lsx_contrast_effect_fn(void)
{
static sox_effect_handler_t handler = {"contrast", "[enhancement (75)]",
0, create, NULL, flow, NULL, NULL, NULL, sizeof(priv_t)};
return &handler;
}

@ -1,418 +0,0 @@
/* AudioCore sound handler
*
* Copyright 2008 Chris Bagwell And Sundry Contributors
*/
#include "sox_i.h"
#include "CoreAudio/CoreAudio.h"
#include <pthread.h>
#define Buffactor 4
typedef struct {
AudioDeviceID adid;
pthread_mutex_t mutex;
pthread_cond_t cond;
int device_started;
size_t bufsize;
size_t bufrd;
size_t bufwr;
size_t bufrdavail;
float *buf;
} priv_t;
static OSStatus PlaybackIOProc(AudioDeviceID inDevice UNUSED,
const AudioTimeStamp *inNow UNUSED,
const AudioBufferList *inInputData UNUSED,
const AudioTimeStamp *inInputTime UNUSED,
AudioBufferList *outOutputData,
const AudioTimeStamp *inOutputTime UNUSED,
void *inClientData)
{
priv_t *ac = (priv_t*)((sox_format_t*)inClientData)->priv;
AudioBuffer *buf;
size_t copylen, avail;
pthread_mutex_lock(&ac->mutex);
for(buf = outOutputData->mBuffers;
buf != outOutputData->mBuffers + outOutputData->mNumberBuffers;
buf++){
copylen = buf->mDataByteSize / sizeof(float);
if(copylen > ac->bufrdavail)
copylen = ac->bufrdavail;
avail = ac->bufsize - ac->bufrd;
if(buf->mData == NULL){
/*do nothing-hardware can't play audio*/
}else if(copylen > avail){
memcpy(buf->mData, ac->buf + ac->bufrd, avail * sizeof(float));
memcpy((float*)buf->mData + avail, ac->buf, (copylen - avail) * sizeof(float));
}else{
memcpy(buf->mData, ac->buf + ac->bufrd, copylen * sizeof(float));
}
buf->mDataByteSize = copylen * sizeof(float);
ac->bufrd += copylen;
if(ac->bufrd >= ac->bufsize)
ac->bufrd -= ac->bufsize;
ac->bufrdavail -= copylen;
}
pthread_cond_signal(&ac->cond);
pthread_mutex_unlock(&ac->mutex);
return kAudioHardwareNoError;
}
static OSStatus RecIOProc(AudioDeviceID inDevice UNUSED,
const AudioTimeStamp *inNow UNUSED,
const AudioBufferList *inInputData,
const AudioTimeStamp *inInputTime UNUSED,
AudioBufferList *outOutputData UNUSED,
const AudioTimeStamp *inOutputTime UNUSED,
void *inClientData)
{
priv_t *ac = (priv_t *)((sox_format_t*)inClientData)->priv;
AudioBuffer const *buf;
size_t nfree, copylen, avail;
pthread_mutex_lock(&ac->mutex);
for(buf = inInputData->mBuffers;
buf != inInputData->mBuffers + inInputData->mNumberBuffers;
buf++){
if(buf->mData == NULL)
continue;
copylen = buf->mDataByteSize / sizeof(float);
nfree = ac->bufsize - ac->bufrdavail - 1;
if(nfree == 0)
lsx_warn("coreaudio: unhandled buffer overrun. Data discarded.");
if(copylen > nfree)
copylen = nfree;
avail = ac->bufsize - ac->bufwr;
if(copylen > avail){
memcpy(ac->buf + ac->bufwr, buf->mData, avail * sizeof(float));
memcpy(ac->buf, (float*)buf->mData + avail, (copylen - avail) * sizeof(float));
}else{
memcpy(ac->buf + ac->bufwr, buf->mData, copylen * sizeof(float));
}
ac->bufwr += copylen;
if(ac->bufwr >= ac->bufsize)
ac->bufwr -= ac->bufsize;
ac->bufrdavail += copylen;
}
pthread_cond_signal(&ac->cond);
pthread_mutex_unlock(&ac->mutex);
return kAudioHardwareNoError;
}
static int setup(sox_format_t *ft, int is_input)
{
priv_t *ac = (priv_t *)ft->priv;
OSStatus status;
UInt32 property_size;
struct AudioStreamBasicDescription stream_desc;
int32_t buf_size;
int rc;
if (strncmp(ft->filename, "default", (size_t)7) == 0)
{
property_size = sizeof(ac->adid);
if (is_input)
status = AudioHardwareGetProperty(kAudioHardwarePropertyDefaultInputDevice, &property_size, &ac->adid);
else
status = AudioHardwareGetProperty(kAudioHardwarePropertyDefaultOutputDevice, &property_size, &ac->adid);
}
else
{
Boolean is_writable;
status = AudioHardwareGetPropertyInfo(kAudioHardwarePropertyDevices, &property_size, &is_writable);
if (status == noErr)
{
int device_count = property_size/sizeof(AudioDeviceID);
AudioDeviceID *devices;
devices = malloc(property_size);
status = AudioHardwareGetProperty(kAudioHardwarePropertyDevices, &property_size, devices);
if (status == noErr)
{
int i;
for (i = 0; i < device_count; i++)
{
char name[256];
status = AudioDeviceGetProperty(devices[i],0,false,kAudioDevicePropertyDeviceName,&property_size,&name);
lsx_report("Found Audio Device \"%s\"\n",name);
/* String returned from OS is truncated so only compare
* as much as returned.
*/
if (strncmp(name,ft->filename,strlen(name)) == 0)
{
ac->adid = devices[i];
break;
}
}
}
free(devices);
}
}
if (status || ac->adid == kAudioDeviceUnknown)
{
lsx_fail_errno(ft, SOX_EPERM, "can not open audio device");
return SOX_EOF;
}
/* Query device to get initial values */
property_size = sizeof(struct AudioStreamBasicDescription);
status = AudioDeviceGetProperty(ac->adid, 0, is_input,
kAudioDevicePropertyStreamFormat,
&property_size, &stream_desc);
if (status)
{
lsx_fail_errno(ft, SOX_EPERM, "can not get audio device properties");
return SOX_EOF;
}
if (!(stream_desc.mFormatFlags & kLinearPCMFormatFlagIsFloat))
{
lsx_fail_errno(ft, SOX_EPERM, "audio device does not accept floats");
return SOX_EOF;
}
/* OS X effectively only supports these values. */
ft->signal.channels = 2;
ft->signal.rate = 44100;
ft->encoding.bits_per_sample = 32;
/* TODO: My limited experience with hardware can only get floats working
* withh a fixed sample rate and stereo. I know that is a limitiation of
* audio device I have so this may not be standard operating orders.
* If some hardware supports setting sample rates and channel counts
* then should do that over resampling and mixing.
*/
#if 0
stream_desc.mSampleRate = ft->signal.rate;
stream_desc.mChannelsPerFrame = ft->signal.channels;
/* Write them back */
property_size = sizeof(struct AudioStreamBasicDescription);
status = AudioDeviceSetProperty(ac->adid, NULL, 0, is_input,
kAudioDevicePropertyStreamFormat,
property_size, &stream_desc);
if (status)
{
lsx_fail_errno(ft, SOX_EPERM, "can not set audio device properties");
return SOX_EOF;
}
/* Query device to see if it worked */
property_size = sizeof(struct AudioStreamBasicDescription);
status = AudioDeviceGetProperty(ac->adid, 0, is_input,
kAudioDevicePropertyStreamFormat,
&property_size, &stream_desc);
if (status)
{
lsx_fail_errno(ft, SOX_EPERM, "can not get audio device properties");
return SOX_EOF;
}
#endif
if (stream_desc.mChannelsPerFrame != ft->signal.channels)
{
lsx_debug("audio device did not accept %d channels. Use %d channels instead.", (int)ft->signal.channels,
(int)stream_desc.mChannelsPerFrame);
ft->signal.channels = stream_desc.mChannelsPerFrame;
}
if (stream_desc.mSampleRate != ft->signal.rate)
{
lsx_debug("audio device did not accept %d sample rate. Use %d instead.", (int)ft->signal.rate,
(int)stream_desc.mSampleRate);
ft->signal.rate = stream_desc.mSampleRate;
}
ac->bufsize = sox_globals.bufsiz / sizeof(sox_sample_t) * Buffactor;
ac->bufrd = 0;
ac->bufwr = 0;
ac->bufrdavail = 0;
ac->buf = lsx_malloc(ac->bufsize * sizeof(float));
buf_size = sox_globals.bufsiz / sizeof(sox_sample_t) * sizeof(float);
property_size = sizeof(buf_size);
status = AudioDeviceSetProperty(ac->adid, NULL, 0, is_input,
kAudioDevicePropertyBufferSize,
property_size, &buf_size);
rc = pthread_mutex_init(&ac->mutex, NULL);
if (rc)
{
lsx_fail_errno(ft, SOX_EPERM, "failed initializing mutex");
return SOX_EOF;
}
rc = pthread_cond_init(&ac->cond, NULL);
if (rc)
{
lsx_fail_errno(ft, SOX_EPERM, "failed initializing condition");
return SOX_EOF;
}
ac->device_started = 0;
/* Registers callback with the device without activating it. */
if (is_input)
status = AudioDeviceAddIOProc(ac->adid, RecIOProc, (void *)ft);
else
status = AudioDeviceAddIOProc(ac->adid, PlaybackIOProc, (void *)ft);
return SOX_SUCCESS;
}
static int startread(sox_format_t *ft)
{
return setup(ft, 1);
}
static size_t read_samples(sox_format_t *ft, sox_sample_t *buf, size_t nsamp)
{
priv_t *ac = (priv_t *)ft->priv;
size_t len;
SOX_SAMPLE_LOCALS;
if (!ac->device_started) {
AudioDeviceStart(ac->adid, RecIOProc);
ac->device_started = 1;
}
pthread_mutex_lock(&ac->mutex);
/* Wait until input buffer has been filled by device driver */
while (ac->bufrdavail == 0)
pthread_cond_wait(&ac->cond, &ac->mutex);
len = 0;
while(len < nsamp && ac->bufrdavail > 0){
buf[len] = SOX_FLOAT_32BIT_TO_SAMPLE(ac->buf[ac->bufrd], ft->clips);
len++;
ac->bufrd++;
if(ac->bufrd == ac->bufsize)
ac->bufrd = 0;
ac->bufrdavail--;
}
pthread_mutex_unlock(&ac->mutex);
return len;
}
static int stopread(sox_format_t * ft)
{
priv_t *ac = (priv_t *)ft->priv;
AudioDeviceStop(ac->adid, RecIOProc);
AudioDeviceRemoveIOProc(ac->adid, RecIOProc);
pthread_cond_destroy(&ac->cond);
pthread_mutex_destroy(&ac->mutex);
free(ac->buf);
return SOX_SUCCESS;
}
static int startwrite(sox_format_t * ft)
{
return setup(ft, 0);
}
static size_t write_samples(sox_format_t *ft, const sox_sample_t *buf, size_t nsamp)
{
priv_t *ac = (priv_t *)ft->priv;
size_t i;
SOX_SAMPLE_LOCALS;
pthread_mutex_lock(&ac->mutex);
/* Wait to start until mutex is locked to help prevent callback
* getting zero samples.
*/
if(!ac->device_started){
if(AudioDeviceStart(ac->adid, PlaybackIOProc)){
pthread_mutex_unlock(&ac->mutex);
return SOX_EOF;
}
ac->device_started = 1;
}
/* globals.bufsize is in samples
* buf_offset is in bytes
* buf_size is in bytes
*/
for(i = 0; i < nsamp; i++){
while(ac->bufrdavail == ac->bufsize - 1)
pthread_cond_wait(&ac->cond, &ac->mutex);
ac->buf[ac->bufwr] = SOX_SAMPLE_TO_FLOAT_32BIT(buf[i], ft->clips);
ac->bufwr++;
if(ac->bufwr == ac->bufsize)
ac->bufwr = 0;
ac->bufrdavail++;
}
pthread_mutex_unlock(&ac->mutex);
return nsamp;
}
static int stopwrite(sox_format_t * ft)
{
priv_t *ac = (priv_t *)ft->priv;
if(ac->device_started){
pthread_mutex_lock(&ac->mutex);
while (ac->bufrdavail > 0)
pthread_cond_wait(&ac->cond, &ac->mutex);
pthread_mutex_unlock(&ac->mutex);
AudioDeviceStop(ac->adid, PlaybackIOProc);
}
AudioDeviceRemoveIOProc(ac->adid, PlaybackIOProc);
pthread_cond_destroy(&ac->cond);
pthread_mutex_destroy(&ac->mutex);
free(ac->buf);
return SOX_SUCCESS;
}
LSX_FORMAT_HANDLER(coreaudio)
{
static char const *const names[] = { "coreaudio", NULL };
static unsigned const write_encodings[] = {
SOX_ENCODING_FLOAT, 32, 0,
0};
static sox_format_handler_t const handler = {SOX_LIB_VERSION_CODE,
"Mac AudioCore device driver",
names, SOX_FILE_DEVICE | SOX_FILE_NOSTDIO,
startread, read_samples, stopread,
startwrite, write_samples, stopwrite,
NULL, write_encodings, NULL, sizeof(priv_t)
};
return &handler;
}

@ -1,165 +0,0 @@
/* libSoX dcshift.c
* (c) 2000.04.15 Chris Ausbrooks <weed@bucket.pp.ualr.edu>
*
* based on vol.c which is
* (c) 20/03/2000 Fabien COELHO <fabien@coelho.net> for sox.
*
* DC shift a sound file, with basic linear amplitude formula.
* Beware of saturations! clipping is checked and reported.
* Cannot handle different number of channels.
* Cannot handle rate change.
*/
#include "sox_i.h"
typedef struct {
double dcshift; /* DC shift. */
int uselimiter; /* boolean: are we using the limiter? */
double limiterthreshhold;
double limitergain; /* limiter gain. */
uint64_t limited; /* number of limited values to report. */
uint64_t totalprocessed;
} priv_t;
/*
* Process options: dcshift (double) type (amplitude, power, dB)
*/
static int sox_dcshift_getopts(sox_effect_t * effp, int argc, char **argv)
{
priv_t * dcs = (priv_t *) effp->priv;
dcs->dcshift = 1.0; /* default is no change */
dcs->uselimiter = 0; /* default is no limiter */
--argc, ++argv;
if (argc < 1)
return lsx_usage(effp);
if (argc && (!sscanf(argv[0], "%lf", &dcs->dcshift)))
return lsx_usage(effp);
if (argc>1)
{
if (!sscanf(argv[1], "%lf", &dcs->limitergain))
return lsx_usage(effp);
dcs->uselimiter = 1; /* ok, we'll use it */
/* 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.) */
dcs->limiterthreshhold = SOX_SAMPLE_MAX * (1.0 - (fabs(dcs->dcshift) - dcs->limitergain));
}
return SOX_SUCCESS;
}
/*
* Start processing
*/
static int sox_dcshift_start(sox_effect_t * effp)
{
priv_t * dcs = (priv_t *) effp->priv;
if (dcs->dcshift == 0)
return SOX_EFF_NULL;
dcs->limited = 0;
dcs->totalprocessed = 0;
return SOX_SUCCESS;
}
/*
* Process data.
*/
static int sox_dcshift_flow(sox_effect_t * effp, const sox_sample_t *ibuf, sox_sample_t *obuf,
size_t *isamp, size_t *osamp)
{
priv_t * dcs = (priv_t *) effp->priv;
double dcshift = dcs->dcshift;
double limitergain = dcs->limitergain;
double limiterthreshhold = dcs->limiterthreshhold;
double sample;
size_t len;
len = min(*osamp, *isamp);
/* report back dealt with amount. */
*isamp = len; *osamp = len;
if (dcs->uselimiter)
{
dcs->totalprocessed += len;
for (;len>0; len--)
{
sample = *ibuf++;
if (sample > limiterthreshhold && dcshift > 0)
{
sample = (sample - limiterthreshhold) * limitergain / (SOX_SAMPLE_MAX - limiterthreshhold) + limiterthreshhold + dcshift;
dcs->limited++;
}
else if (sample < -limiterthreshhold && dcshift < 0)
{
/* Note this should really be SOX_SAMPLE_MIN but
* the clip() below will take care of the overflow.
*/
sample = (sample + limiterthreshhold) * limitergain / (SOX_SAMPLE_MAX - limiterthreshhold) - limiterthreshhold + dcshift;
dcs->limited++;
}
else
{
/* Note this should consider SOX_SAMPLE_MIN but
* the clip() below will take care of the overflow.
*/
sample = dcshift * SOX_SAMPLE_MAX + sample;
}
SOX_SAMPLE_CLIP_COUNT(sample, effp->clips);
*obuf++ = sample;
}
}
else for (; len > 0; --len) { /* quite basic, with clipping */
double d = dcshift * (SOX_SAMPLE_MAX + 1.) + *ibuf++;
*obuf++ = SOX_ROUND_CLIP_COUNT(d, effp->clips);
}
return SOX_SUCCESS;
}
/*
* Do anything required when you stop reading samples.
* Don't close input file!
*/
static int sox_dcshift_stop(sox_effect_t * effp)
{
priv_t * dcs = (priv_t *) effp->priv;
if (dcs->limited)
{
lsx_warn("DCSHIFT limited %" PRIu64 " values (%d percent).",
dcs->limited, (int) (dcs->limited * 100.0 / dcs->totalprocessed));
}
return SOX_SUCCESS;
}
static sox_effect_handler_t sox_dcshift_effect = {
"dcshift",
"shift [ limitergain ]\n"
"\tThe peak limiter has a gain much less than 1.0 (ie 0.05 or 0.02) which\n"
"\tis only used on peaks to prevent clipping. (default is no limiter)",
SOX_EFF_MCHAN | SOX_EFF_GAIN,
sox_dcshift_getopts,
sox_dcshift_start,
sox_dcshift_flow,
NULL,
sox_dcshift_stop,
NULL, sizeof(priv_t)
};
const sox_effect_handler_t *lsx_dcshift_effect_fn(void)
{
return &sox_dcshift_effect;
}

@ -1,137 +0,0 @@
/* Abstract effect: dft filter 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"
#include "fft4g.h"
#include "dft_filter.h"
#include <string.h>
typedef dft_filter_t filter_t;
typedef dft_filter_priv_t priv_t;
void lsx_set_dft_filter(dft_filter_t *f, double *h, int n, int post_peak)
{
int i;
f->num_taps = n;
f->post_peak = post_peak;
f->dft_length = lsx_set_dft_length(f->num_taps);
f->coefs = lsx_calloc(f->dft_length, sizeof(*f->coefs));
for (i = 0; i < f->num_taps; ++i)
f->coefs[(i + f->dft_length - f->num_taps + 1) & (f->dft_length - 1)] = h[i] / f->dft_length * 2;
lsx_safe_rdft(f->dft_length, 1, f->coefs);
free(h);
}
static int start(sox_effect_t * effp)
{
priv_t * p = (priv_t *) effp->priv;
fifo_create(&p->input_fifo, (int)sizeof(double));
memset(fifo_reserve(&p->input_fifo,
p->filter_ptr->post_peak), 0, sizeof(double) * p->filter_ptr->post_peak);
fifo_create(&p->output_fifo, (int)sizeof(double));
return SOX_SUCCESS;
}
static void filter(priv_t * p)
{
int i, num_in = max(0, fifo_occupancy(&p->input_fifo));
filter_t const * f = p->filter_ptr;
int const overlap = f->num_taps - 1;
double * output;
while (num_in >= f->dft_length) {
double const * input = fifo_read_ptr(&p->input_fifo);
fifo_read(&p->input_fifo, f->dft_length - overlap, NULL);
num_in -= f->dft_length - overlap;
output = fifo_reserve(&p->output_fifo, f->dft_length);
fifo_trim_by(&p->output_fifo, overlap);
memcpy(output, input, f->dft_length * sizeof(*output));
lsx_safe_rdft(f->dft_length, 1, output);
output[0] *= f->coefs[0];
output[1] *= f->coefs[1];
for (i = 2; i < f->dft_length; i += 2) {
double tmp = output[i];
output[i ] = f->coefs[i ] * tmp - f->coefs[i+1] * output[i+1];
output[i+1] = f->coefs[i+1] * tmp + f->coefs[i ] * output[i+1];
}
lsx_safe_rdft(f->dft_length, -1, output);
}
}
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 odone = min(*osamp, (size_t)fifo_occupancy(&p->output_fifo));
double const * s = fifo_read(&p->output_fifo, (int)odone, NULL);
lsx_save_samples(obuf, s, odone, &effp->clips);
p->samples_out += odone;
if (*isamp && odone < *osamp) {
double * t = fifo_write(&p->input_fifo, (int)*isamp, NULL);
p->samples_in += *isamp;
lsx_load_samples(t, ibuf, *isamp);
filter(p);
}
else *isamp = 0;
*osamp = odone;
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;
size_t remaining = p->samples_in > p->samples_out ?
(size_t)(p->samples_in - p->samples_out) : 0;
double * buff = lsx_calloc(1024, sizeof(*buff));
if (remaining > 0) {
while ((size_t)fifo_occupancy(&p->output_fifo) < remaining) {
fifo_write(&p->input_fifo, 1024, buff);
p->samples_in += 1024;
filter(p);
}
fifo_trim_to(&p->output_fifo, (int)remaining);
p->samples_in = 0;
}
free(buff);
return flow(effp, 0, obuf, &isamp, osamp);
}
static int stop(sox_effect_t * effp)
{
priv_t * p = (priv_t *) effp->priv;
fifo_delete(&p->input_fifo);
fifo_delete(&p->output_fifo);
free(p->filter_ptr->coefs);
memset(p->filter_ptr, 0, sizeof(*p->filter_ptr));
return SOX_SUCCESS;
}
sox_effect_handler_t const * lsx_dft_filter_effect_fn(void)
{
static sox_effect_handler_t handler = {
NULL, NULL, SOX_EFF_GAIN, NULL, start, flow, drain, stop, NULL, 0
};
return &handler;
}

@ -1,16 +0,0 @@
#include "fft4g.h"
#define FIFO_SIZE_T int
#include "fifo.h"
typedef struct {
int dft_length, num_taps, post_peak;
double * coefs;
} dft_filter_t;
typedef struct {
uint64_t samples_in, samples_out;
fifo_t input_fifo, output_fifo;
dft_filter_t filter, * filter_ptr;
} dft_filter_priv_t;
void lsx_set_dft_filter(dft_filter_t * f, double * h, int n, int post_peak);

@ -1,436 +0,0 @@
/* Effect: dither/noise-shape Copyright (c) 2008-9 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>
#undef RANQD1
#define RANQD1 ranqd1(p->ranqd1)
typedef enum { /* Collection of various filters from the net */
Shape_none, Shape_lipshitz, Shape_f_weighted, Shape_modified_e_weighted,
Shape_improved_e_weighted, Shape_gesemann, Shape_shibata, Shape_low_shibata, Shape_high_shibata
} filter_name_t;
static lsx_enum_item const filter_names[] = {
LSX_ENUM_ITEM(Shape_,none)
LSX_ENUM_ITEM(Shape_,lipshitz)
{"f-weighted", Shape_f_weighted},
{"modified-e-weighted", Shape_modified_e_weighted},
{"improved-e-weighted", Shape_improved_e_weighted},
LSX_ENUM_ITEM(Shape_,gesemann)
LSX_ENUM_ITEM(Shape_,shibata)
{"low-shibata", Shape_low_shibata},
{"high-shibata", Shape_high_shibata},
{0, 0}};
typedef struct {
sox_rate_t rate;
enum {fir, iir} type;
size_t len;
int gain_cB; /* Chosen so clips are few if any, but not guaranteed none. */
double const * coefs;
filter_name_t name;
} filter_t;
static double const lip44[] = {2.033, -2.165, 1.959, -1.590, .6149};
static double const fwe44[] = {
2.412, -3.370, 3.937, -4.174, 3.353, -2.205, 1.281, -.569, .0847};
static double const mew44[] = {
1.662, -1.263, .4827, -.2913, .1268, -.1124, .03252, -.01265, -.03524};
static double const iew44[] = {
2.847, -4.685, 6.214, -7.184, 6.639, -5.032, 3.263, -1.632, .4191};
static double const ges44[] = {
2.2061, -.4706, -.2534, -.6214, 1.0587, .0676, -.6054, -.2738};
static double const ges48[] = {
2.2374, -.7339, -.1251, -.6033, .903, .0116, -.5853, -.2571};
static double const shi48[] = {
2.8720729351043701172, -5.0413231849670410156, 6.2442994117736816406,
-5.8483986854553222656, 3.7067542076110839844, -1.0495119094848632812,
-1.1830236911773681641, 2.1126792430877685547, -1.9094531536102294922,
0.99913084506988525391, -0.17090806365013122559, -0.32615602016448974609,
0.39127644896507263184, -0.26876461505889892578, 0.097676105797290802002,
-0.023473845794796943665,
};
static double const shi44[] = {
2.6773197650909423828, -4.8308925628662109375, 6.570110321044921875,
-7.4572014808654785156, 6.7263274192810058594, -4.8481650352478027344,
2.0412089824676513672, 0.7006359100341796875, -2.9537565708160400391,
4.0800385475158691406, -4.1845216751098632812, 3.3311812877655029297,
-2.1179926395416259766, 0.879302978515625, -0.031759146600961685181,
-0.42382788658142089844, 0.47882103919982910156, -0.35490813851356506348,
0.17496839165687561035, -0.060908168554306030273,
};
static double const shi38[] = {
1.6335992813110351562, -2.2615492343902587891, 2.4077029228210449219,
-2.6341717243194580078, 2.1440362930297851562, -1.8153258562088012695,
1.0816224813461303711, -0.70302653312683105469, 0.15991993248462677002,
0.041549518704414367676, -0.29416576027870178223, 0.2518316805362701416,
-0.27766478061676025391, 0.15785403549671173096, -0.10165894031524658203,
0.016833892092108726501,
};
static double const shi32[] =
{ /* dmaker 32000: bestmax=4.99659 (inverted) */
0.82118552923202515,
-1.0063692331314087,
0.62341964244842529,
-1.0447187423706055,
0.64532512426376343,
-0.87615132331848145,
0.52219754457473755,
-0.67434263229370117,
0.44954317808151245,
-0.52557498216629028,
0.34567299485206604,
-0.39618203043937683,
0.26791760325431824,
-0.28936097025871277,
0.1883765310049057,
-0.19097308814525604,
0.10431359708309174,
-0.10633844882249832,
0.046832218766212463,
-0.039653312414884567,
};
static double const shi22[] =
{ /* dmaker 22050: bestmax=5.77762 (inverted) */
0.056581053882837296,
-0.56956905126571655,
-0.40727734565734863,
-0.33870288729667664,
-0.29810553789138794,
-0.19039161503314972,
-0.16510021686553955,
-0.13468159735202789,
-0.096633769571781158,
-0.081049129366874695,
-0.064953058958053589,
-0.054459091275930405,
-0.043378707021474838,
-0.03660014271736145,
-0.026256965473294258,
-0.018786206841468811,
-0.013387725688517094,
-0.0090983230620622635,
-0.0026585909072309732,
-0.00042083300650119781,
};
static double const shi16[] =
{ /* dmaker 16000: bestmax=5.97128 (inverted) */
-0.37251132726669312,
-0.81423574686050415,
-0.55010956525802612,
-0.47405767440795898,
-0.32624706625938416,
-0.3161766529083252,
-0.2286367267370224,
-0.22916607558727264,
-0.19565616548061371,
-0.18160104751586914,
-0.15423151850700378,
-0.14104481041431427,
-0.11844276636838913,
-0.097583092749118805,
-0.076493598520755768,
-0.068106919527053833,
-0.041881654411554337,
-0.036922425031661987,
-0.019364040344953537,
-0.014994367957115173,
};
static double const shi11[] =
{ /* dmaker 11025: bestmax=5.9406 (inverted) */
-0.9264228343963623,
-0.98695987462997437,
-0.631156325340271,
-0.51966935396194458,
-0.39738872647285461,
-0.35679301619529724,
-0.29720726609230042,
-0.26310476660728455,
-0.21719355881214142,
-0.18561814725399017,
-0.15404847264289856,
-0.12687471508979797,
-0.10339745879173279,
-0.083688631653785706,
-0.05875682458281517,
-0.046893671154975891,
-0.027950936928391457,
-0.020740609616041183,
-0.009366452693939209,
-0.0060260160826146603,
};
static double const shi08[] =
{ /* dmaker 8000: bestmax=5.56234 (inverted) */
-1.202863335609436,
-0.94103097915649414,
-0.67878556251525879,
-0.57650017738342285,
-0.50004476308822632,
-0.44349345564842224,
-0.37833768129348755,
-0.34028723835945129,
-0.29413089156150818,
-0.24994957447052002,
-0.21715600788593292,
-0.18792112171649933,
-0.15268312394618988,
-0.12135542929172516,
-0.099610626697540283,
-0.075273610651493073,
-0.048787496984004974,
-0.042586319148540497,
-0.028991291299462318,
-0.011869125068187714,
};
static double const shl48[] = {
2.3925774097442626953, -3.4350297451019287109, 3.1853709220886230469,
-1.8117271661758422852, -0.20124770700931549072, 1.4759907722473144531,
-1.7210904359817504883, 0.97746700048446655273, -0.13790138065814971924,
-0.38185903429985046387, 0.27421241998672485352, 0.066584214568138122559,
-0.35223302245140075684, 0.37672343850135803223, -0.23964276909828186035,
0.068674825131893157959,
};
static double const shl44[] = {
2.0833916664123535156, -3.0418450832366943359, 3.2047898769378662109,
-2.7571926116943359375, 1.4978630542755126953, -0.3427594602108001709,
-0.71733748912811279297, 1.0737057924270629883, -1.0225815773010253906,
0.56649994850158691406, -0.20968692004680633545, -0.065378531813621520996,
0.10322438180446624756, -0.067442022264003753662, -0.00495197344571352005,
};
static double const shh44[] = {
3.0259189605712890625, -6.0268716812133789062, 9.195003509521484375,
-11.824929237365722656, 12.767142295837402344, -11.917946815490722656,
9.1739168167114257812, -5.3712320327758789062, 1.1393624544143676758,
2.4484779834747314453, -4.9719839096069335938, 6.0392003059387207031,
-5.9359521865844726562, 4.903278350830078125, -3.5527443885803222656,
2.1909697055816650391, -1.1672389507293701172, 0.4903914332389831543,
-0.16519790887832641602, 0.023217858746647834778,
};
static const filter_t filters[] = {
{44100, fir, 5, 210, lip44, Shape_lipshitz},
{46000, fir, 9, 276, fwe44, Shape_f_weighted},
{46000, fir, 9, 160, mew44, Shape_modified_e_weighted},
{46000, fir, 9, 321, iew44, Shape_improved_e_weighted},
{48000, iir, 4, 220, ges48, Shape_gesemann},
{44100, iir, 4, 230, ges44, Shape_gesemann},
{48000, fir, 16, 301, shi48, Shape_shibata},
{44100, fir, 20, 333, shi44, Shape_shibata},
{37800, fir, 16, 240, shi38, Shape_shibata},
{32000, fir, 20, 240/*TBD*/, shi32, Shape_shibata},
{22050, fir, 20, 240/*TBD*/, shi22, Shape_shibata},
{16000, fir, 20, 240/*TBD*/, shi16, Shape_shibata},
{11025, fir, 20, 240/*TBD*/, shi11, Shape_shibata},
{ 8000, fir, 20, 240/*TBD*/, shi08, Shape_shibata},
{48000, fir, 16, 250, shl48, Shape_low_shibata},
{44100, fir, 15, 250, shl44, Shape_low_shibata},
{44100, fir, 20, 383, shh44, Shape_high_shibata},
{ 0, fir, 0, 0, NULL, Shape_none},
};
#define MAX_N 20
typedef struct {
filter_name_t filter_name;
sox_bool auto_detect, alt_tpdf;
double dummy;
double previous_errors[MAX_N * 2];
double previous_outputs[MAX_N * 2];
size_t pos, prec;
uint64_t num_output;
int32_t history, ranqd1, r;
double const * coefs;
sox_bool dither_off;
sox_effect_handler_flow flow;
} priv_t;
#define CONVOLVE _ _ _ _
#define NAME flow_iir_4
#define IIR
#define N 4
#include "dither.h"
#undef IIR
#define CONVOLVE _ _ _ _ _
#define NAME flow_fir_5
#define N 5
#include "dither.h"
#define CONVOLVE _ _ _ _ _ _ _ _ _
#define NAME flow_fir_9
#define N 9
#include "dither.h"
#define CONVOLVE _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
#define NAME flow_fir_15
#define N 15
#include "dither.h"
#define CONVOLVE _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
#define NAME flow_fir_16
#define N 16
#include "dither.h"
#define CONVOLVE _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
#define NAME flow_fir_20
#define N 20
#include "dither.h"
static int flow_no_shape(sox_effect_t * effp, const sox_sample_t * ibuf,
sox_sample_t * obuf, size_t * isamp, size_t * osamp)
{
priv_t * p = (priv_t *)effp->priv;
size_t len = *isamp = *osamp = min(*isamp, *osamp);
while (len--) {
if (p->auto_detect) {
p->history = (p->history << 1) +
!!(*ibuf & (((unsigned)-1) >> p->prec));
if (p->history && p->dither_off) {
p->dither_off = sox_false;
lsx_debug("flow %" PRIuPTR ": on @ %" PRIu64, effp->flow, p->num_output);
} else if (!p->history && !p->dither_off) {
p->dither_off = sox_true;
lsx_debug("flow %" PRIuPTR ": off @ %" PRIu64, effp->flow, p->num_output);
}
}
if (!p->dither_off) {
int32_t r = RANQD1 >> p->prec;
double d = ((double)*ibuf++ + r + (p->alt_tpdf? -p->r : (RANQD1 >> p->prec))) / (1 << (32 - p->prec));
int i = d < 0? d - .5 : d + .5;
p->r = r;
if (i <= (-1 << (p->prec-1)))
++effp->clips, *obuf = SOX_SAMPLE_MIN;
else if (i > (int)SOX_INT_MAX(p->prec))
++effp->clips, *obuf = SOX_INT_MAX(p->prec) << (32 - p->prec);
else *obuf = i << (32 - p->prec);
++obuf;
}
else
*obuf++ = *ibuf++;
++p->num_output;
}
return SOX_SUCCESS;
}
static int getopts(sox_effect_t * effp, int argc, char * * argv)
{
priv_t * p = (priv_t *)effp->priv;
int c;
lsx_getopt_t optstate;
lsx_getopt_init(argc, argv, "+aSsf:p:", NULL, lsx_getopt_flag_none, 1, &optstate);
while ((c = lsx_getopt(&optstate)) != -1) switch (c) {
case 'a': p->auto_detect = sox_true; break;
case 'S': p->alt_tpdf = sox_true; break;
case 's': p->filter_name = Shape_shibata; break;
case 'f':
p->filter_name = lsx_enum_option(c, optstate.arg, filter_names);
if (p->filter_name == INT_MAX)
return SOX_EOF;
break;
GETOPT_NUMERIC(optstate, 'p', prec, 1, 24)
default: lsx_fail("invalid option `-%c'", optstate.opt); return lsx_usage(effp);
}
argc -= optstate.ind, argv += optstate.ind;
return argc? lsx_usage(effp) : SOX_SUCCESS;
}
static int start(sox_effect_t * effp)
{
priv_t * p = (priv_t *)effp->priv;
double mult = 1; /* Amount the noise shaping multiplies up the TPDF (+/-1) */
if (p->prec == 0)
p->prec = effp->out_signal.precision;
if (effp->in_signal.precision <= p->prec || p->prec > 24)
return SOX_EFF_NULL; /* Dithering not needed at this resolution */
if (p->prec == 1) {
/* The general dither routines don't work in this case, so notify
user and leave it at that for now.
TODO: Some special-case treatment of 1-bit noise shaping will be
needed for meaningful DSD write support. */
lsx_warn("Dithering/noise-shaping to 1 bit is currently not supported.");
return SOX_EFF_NULL;
}
effp->out_signal.precision = p->prec;
p->flow = flow_no_shape;
if (p->filter_name) {
filter_t const * f;
for (f = filters; f->len && (f->name != p->filter_name || fabs(effp->in_signal.rate - f->rate) / f->rate > .05); ++f); /* 5% leeway on frequency */
if (!f->len) {
p->alt_tpdf |= effp->in_signal.rate >= 22050;
if (!effp->flow)
lsx_warn("no `%s' filter is available for rate %g; using %s TPDF",
lsx_find_enum_value(p->filter_name, filter_names)->text,
effp->in_signal.rate, p->alt_tpdf? "sloped" : "plain");
}
else {
assert(f->len <= MAX_N);
if (f->type == fir) switch(f->len) {
case 5: p->flow = flow_fir_5 ; break;
case 9: p->flow = flow_fir_9 ; break;
case 15: p->flow = flow_fir_15; break;
case 16: p->flow = flow_fir_16; break;
case 20: p->flow = flow_fir_20; break;
default: assert(sox_false);
} else switch(f->len) {
case 4: p->flow = flow_iir_4 ; break;
default: assert(sox_false);
}
p->coefs = f->coefs;
mult = dB_to_linear(f->gain_cB * 0.1);
}
}
p->ranqd1 = ranqd1(sox_globals.ranqd1) + effp->flow;
if (effp->in_signal.mult) /* (Takes account of ostart mult (sox.c). */
*effp->in_signal.mult *= (SOX_SAMPLE_MAX - (1 << (31 - p->prec)) *
(2 * mult + 1)) / (SOX_SAMPLE_MAX - (1 << (31 - p->prec)));
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;
return p->flow(effp, ibuf, obuf, isamp, osamp);
}
sox_effect_handler_t const * lsx_dither_effect_fn(void)
{
static sox_effect_handler_t handler = {
"dither", "[-S|-s|-f filter] [-a] [-p precision]"
"\n (none) Use TPDF"
"\n -S Use sloped TPDF (without noise shaping)"
"\n -s Shape noise (with shibata filter)"
"\n -f name Set shaping filter to one of: lipshitz, f-weighted,"
"\n modified-e-weighted, improved-e-weighted, gesemann,"
"\n shibata, low-shibata, high-shibata."
"\n -a Automatically turn on & off dithering as needed (use with caution!)"
"\n -p bits Override the target sample precision",
SOX_EFF_PREC, getopts, start, flow, 0, 0, 0, sizeof(priv_t)
};
return &handler;
}

@ -1,63 +0,0 @@
#ifdef IIR
#define _ output += p->coefs[j] * p->previous_errors[p->pos + j] \
- p->coefs[N + j] * p->previous_outputs[p->pos + j], ++j;
#else
#define _ d -= p->coefs[j] * p->previous_errors[p->pos + j], ++j;
#endif
static int NAME(sox_effect_t * effp, const sox_sample_t * ibuf,
sox_sample_t * obuf, size_t * isamp, size_t * osamp)
{
priv_t * p = (priv_t *)effp->priv;
size_t len = *isamp = *osamp = min(*isamp, *osamp);
while (len--) {
if (p->auto_detect) {
p->history = (p->history << 1) +
!!(*ibuf & (((unsigned)-1) >> p->prec));
if (p->history && p->dither_off) {
p->dither_off = sox_false;
lsx_debug("flow %" PRIuPTR ": on @ %" PRIu64, effp->flow, p->num_output);
} else if (!p->history && !p->dither_off) {
p->dither_off = sox_true;
memset(p->previous_errors, 0, sizeof(p->previous_errors));
memset(p->previous_outputs, 0, sizeof(p->previous_outputs));
lsx_debug("flow %" PRIuPTR ": off @ %" PRIu64, effp->flow, p->num_output);
}
}
if (!p->dither_off) {
int32_t r1 = RANQD1 >> p->prec, r2 = RANQD1 >> p->prec; /* Defer add! */
#ifdef IIR
double d1, d, output = 0;
#else
double d1, d = *ibuf++;
#endif
int i, j = 0;
CONVOLVE
assert(j == N);
p->pos = p->pos? p->pos - 1 : p->pos - 1 + N;
#ifdef IIR
d = *ibuf++ - output;
p->previous_outputs[p->pos + N] = p->previous_outputs[p->pos] = output;
#endif
d1 = (d + r1 + r2) / (1 << (32 - p->prec));
i = d1 < 0? d1 - .5 : d1 + .5;
p->previous_errors[p->pos + N] = p->previous_errors[p->pos] =
(double)i * (1 << (32 - p->prec)) - d;
if (i < (-1 << (p->prec-1)))
++effp->clips, *obuf = SOX_SAMPLE_MIN;
else if (i > (int)SOX_INT_MAX(p->prec))
++effp->clips, *obuf = SOX_INT_MAX(p->prec) << (32 - p->prec);
else *obuf = i << (32 - p->prec);
++obuf;
}
else
*obuf++ = *ibuf++;
++p->num_output;
}
return SOX_SUCCESS;
}
#undef CONVOLVE
#undef _
#undef NAME
#undef N

@ -1,73 +0,0 @@
/* libSoX effect: divide Copyright (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
*/
/* This is W.I.P. hence marked SOX_EFF_ALPHA for now.
* Needs better handling of when the divisor approaches or is zero; some
* sort of interpolation of the output values perhaps.
*/
#include "sox_i.h"
#include <string.h>
typedef struct {
sox_sample_t * last;
} priv_t;
static int start(sox_effect_t * effp)
{
priv_t * p = (priv_t *)effp->priv;
p->last = lsx_calloc(effp->in_signal.channels, sizeof(*p->last));
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, len = min(*isamp, *osamp) / effp->in_signal.channels;
*osamp = *isamp = len * effp->in_signal.channels;
while (len--) {
double divisor = *obuf++ = *ibuf++;
if (divisor) {
double out, mult = 1. / SOX_SAMPLE_TO_FLOAT_64BIT(divisor,);
for (i = 1; i < effp->in_signal.channels; ++i) {
out = *ibuf++ * mult;
p->last[i] = *obuf++ = SOX_ROUND_CLIP_COUNT(out, effp->clips);
}
}
else for (i = 1; i < effp->in_signal.channels; ++i, ++ibuf)
*obuf++ = p->last[i];
}
return SOX_SUCCESS;
}
static int stop(sox_effect_t * effp)
{
priv_t * p = (priv_t *)effp->priv;
free(p->last);
return SOX_SUCCESS;
}
sox_effect_handler_t const * lsx_divide_effect_fn(void)
{
static sox_effect_handler_t handler = {
"divide", NULL, SOX_EFF_MCHAN | SOX_EFF_GAIN | SOX_EFF_ALPHA,
NULL, start, flow, NULL, stop, NULL, sizeof(priv_t)
};
return &handler;
}

@ -1,97 +0,0 @@
/* libSoX earwax - makes listening to headphones easier November 9, 2000
*
* Copyright (c) 2000 Edward Beingessner And Sundry Contributors.
* This source code is freely redistributable and may be used for any purpose.
* This copyright notice must be maintained. Edward Beingessner And Sundry
* Contributors are not responsible for the consequences of using this
* software.
*
* This effect takes a 44.1kHz stereo (CD format) signal that is meant to be
* listened to on headphones, and adds audio cues to move the soundstage from
* inside your head (standard for headphones) to outside and in front of the
* listener (standard for speakers). This makes the sound much easier to listen
* to on headphones.
*/
#include "sox_i.h"
#include <string.h>
static const sox_sample_t filt[32 * 2] = {
/* 30° 330° */
4, -6, /* 32 tap stereo FIR filter. */
4, -11, /* One side filters as if the */
-1, -5, /* signal was from 30 degrees */
3, 3, /* from the ear, the other as */
-2, 5, /* if 330 degrees. */
-5, 0,
9, 1,
6, 3, /* Input */
-4, -1, /* Left Right */
-5, -3, /* __________ __________ */
-2, -5, /* | | | | */
-7, 1, /* .---| Hh,0(f) | | Hh,0(f) |---. */
6, -7, /* / |__________| |__________| \ */
30, -29, /* / \ / \ */
12, -3, /* / X \ */
-11, 4, /* / / \ \ */
-3, 7, /* ____V_____ __________V V__________ _____V____ */
-20, 23, /* | | | | | | | | */
2, 0, /* | Hh,30(f) | | Hh,330(f)| | Hh,330(f)| | Hh,30(f) | */
1, -6, /* |__________| |__________| |__________| |__________| */
-14, -5, /* \ ___ / \ ___ / */
15, -18, /* \ / \ / _____ \ / \ / */
6, 7, /* `->| + |<--' / \ `-->| + |<-' */
15, -10, /* \___/ _/ \_ \___/ */
-14, 22, /* \ / \ / \ / */
-7, -2, /* `--->| | | |<---' */
-4, 9, /* \_/ \_/ */
6, -12, /* */
6, -6, /* Headphones */
0, -11,
0, -5,
4, 0};
#define NUMTAPS array_length(filt)
typedef struct {sox_sample_t tap[NUMTAPS];} priv_t; /* FIR filter z^-1 delays */
static int start(sox_effect_t * effp)
{
priv_t * p = (priv_t *)effp->priv;
if (effp->in_signal.rate != 44100 || effp->in_signal.channels != 2) {
lsx_fail("works only with stereo audio sampled at 44100Hz (i.e. CDDA)");
return SOX_EOF;
}
memset(p->tap, 0, NUMTAPS * sizeof(*p->tap)); /* zero tap memory */
if (effp->in_signal.mult)
*effp->in_signal.mult *= dB_to_linear(-4.4);
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, len = *isamp = *osamp = min(*isamp, *osamp);
while (len--) { /* update taps and calculate output */
double output = 0;
for (i = NUMTAPS - 1; i; --i) {
p->tap[i] = p->tap[i - 1];
output += p->tap[i] * filt[i];
}
p->tap[0] = *ibuf++ / 64; /* scale output */
output += p->tap[0] * filt[0];
*obuf++ = SOX_ROUND_CLIP_COUNT(output, effp->clips);
}
return SOX_SUCCESS;
}
/* No drain: preserve audio file length; it's only 32 samples anyway. */
sox_effect_handler_t const *lsx_earwax_effect_fn(void)
{
static sox_effect_handler_t handler = {"earwax", NULL, SOX_EFF_MCHAN,
NULL, start, flow, NULL, NULL, NULL, sizeof(priv_t)};
return &handler;
}

@ -15,59 +15,16 @@
/* FIXME: generate this list automatically */
EFFECT(allpass)
EFFECT(band)
EFFECT(bandpass)
EFFECT(bandreject)
EFFECT(bass)
EFFECT(bend)
EFFECT(biquad)
EFFECT(chorus)
EFFECT(channels)
EFFECT(compand)
EFFECT(contrast)
EFFECT(dcshift)
EFFECT(deemph)
EFFECT(delay)
EFFECT(dft_filter) /* abstract */
EFFECT(dither)
EFFECT(divide)
EFFECT(downsample)
EFFECT(earwax)
EFFECT(echo)
EFFECT(echos)
EFFECT(equalizer)
EFFECT(fade)
EFFECT(fir)
EFFECT(firfit)
EFFECT(flanger)
EFFECT(gain)
EFFECT(highpass)
EFFECT(hilbert)
EFFECT(input)
#ifdef HAVE_LADSPA_H
EFFECT(ladspa)
#endif
EFFECT(loudness)
EFFECT(lowpass)
EFFECT(mcompand)
EFFECT(noiseprof)
EFFECT(noisered)
EFFECT(norm)
EFFECT(oops)
EFFECT(output)
EFFECT(overdrive)
EFFECT(pad)
EFFECT(phaser)
EFFECT(pitch)
EFFECT(rate)
EFFECT(remix)
EFFECT(repeat)
EFFECT(reverb)
EFFECT(reverse)
EFFECT(riaa)
EFFECT(silence)
EFFECT(sinc)
#ifdef HAVE_PNG
EFFECT(spectrogram)
#endif
@ -75,16 +32,7 @@
#ifdef HAVE_SPEEXDSP
EFFECT(speexdsp)
#endif
EFFECT(splice)
EFFECT(stat)
EFFECT(stats)
EFFECT(stretch)
EFFECT(swap)
EFFECT(synth)
EFFECT(tempo)
EFFECT(treble)
EFFECT(tremolo)
EFFECT(trim)
EFFECT(upsample)
EFFECT(vad)
EFFECT(vol)

@ -1,21 +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
*/
#include "sox_i.h"
#include "raw.h"
RAW_FORMAT1(f4, "f32", 32, 0, FLOAT)

@ -1,21 +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
*/
#include "sox_i.h"
#include "raw.h"
RAW_FORMAT1(f8, "f64", 64, 0, FLOAT)

@ -1,399 +0,0 @@
/* Ari Moisio <armoi@sci.fi> Aug 29 2000, based on skeleton effect
* Written by Chris Bagwell (cbagwell@sprynet.com) - March 16, 1999
*
* Copyright 1999 Chris Bagwell And Sundry Contributors
* This source code is freely redistributable and may be used for
* any purpose. This copyright notice must be maintained.
* Chris Bagwell And Sundry Contributors are not responsible for
* the consequences of using this software.
*/
#include "sox_i.h"
/* Fade curves */
#define FADE_QUARTER 'q' /* Quarter of sine wave, 0 to pi/2 */
#define FADE_HALF 'h' /* Half of sine wave, pi/2 to 1.5 * pi
* scaled so that -1 means no output
* and 1 means 0 db attenuation. */
#define FADE_LOG 'l' /* Logarithmic curve. Fades -100 db
* in given time. */
#define FADE_TRI 't' /* Linear slope. */
#define FADE_PAR 'p' /* Inverted parabola. */
#include <string.h>
/* Private data for fade file */
typedef struct { /* These are measured as samples */
uint64_t in_start, in_stop, out_start, out_stop, samplesdone;
char *in_stop_str, *out_start_str, *out_stop_str;
char in_fadetype, out_fadetype;
char do_out;
int endpadwarned;
} priv_t;
/* prototypes */
static double fade_gain(uint64_t index, uint64_t range, int fadetype);
/*
* Process options
*
* Don't do initialization now.
* The 'info' fields are not yet filled in.
*/
static int sox_fade_getopts(sox_effect_t * effp, int argc, char **argv)
{
priv_t * fade = (priv_t *) effp->priv;
char t_char[2];
int t_argno;
uint64_t samples;
const char *n;
--argc, ++argv;
if (argc < 1 || argc > 4)
return lsx_usage(effp);
/* because sample rate is unavailable at this point we store the
* string off for later computations.
*/
if (sscanf(argv[0], "%1[qhltp]", t_char))
{
fade->in_fadetype = *t_char;
fade->out_fadetype = *t_char;
argv++;
argc--;
}
else
{
/* No type given. */
fade->in_fadetype = 'l';
fade->out_fadetype = 'l';
}
fade->in_stop_str = lsx_strdup(argv[0]);
/* Do a dummy parse to see if it will fail */
n = lsx_parsesamples(0., fade->in_stop_str, &samples, 't');
if (!n || *n)
return lsx_usage(effp);
fade->in_stop = samples;
fade->out_start_str = fade->out_stop_str = 0;
for (t_argno = 1; t_argno < argc && t_argno < 3; t_argno++)
{
/* See if there is fade-in/fade-out times/curves specified. */
if(t_argno == 1)
{
fade->out_stop_str = lsx_strdup(argv[t_argno]);
/* Do a dummy parse to see if it will fail */
n = lsx_parseposition(0., fade->out_stop_str, NULL, (uint64_t)0, (uint64_t)0, '=');
if (!n || *n)
return lsx_usage(effp);
fade->out_stop = samples;
}
else
{
fade->out_start_str = lsx_strdup(argv[t_argno]);
/* Do a dummy parse to see if it will fail */
n = lsx_parsesamples(0., fade->out_start_str, &samples, 't');
if (!n || *n)
return lsx_usage(effp);
fade->out_start = samples;
}
} /* End for(t_argno) */
return(SOX_SUCCESS);
}
/*
* Prepare processing.
* Do all initializations.
*/
static int sox_fade_start(sox_effect_t * effp)
{
priv_t * fade = (priv_t *) effp->priv;
sox_bool truncate = sox_false;
uint64_t samples;
uint64_t in_length = effp->in_signal.length != SOX_UNKNOWN_LEN ?
effp->in_signal.length / effp->in_signal.channels : SOX_UNKNOWN_LEN;
/* converting time values to samples */
fade->in_start = 0;
if (lsx_parsesamples(effp->in_signal.rate, fade->in_stop_str,
&samples, 't') == NULL)
return lsx_usage(effp);
fade->in_stop = samples;
fade->do_out = 0;
/* See if user specified a stop time */
if (fade->out_stop_str)
{
fade->do_out = 1;
if (!lsx_parseposition(effp->in_signal.rate, fade->out_stop_str,
&samples, (uint64_t)0, in_length, '=') ||
samples == SOX_UNKNOWN_LEN) {
lsx_fail("audio length is unknown");
return SOX_EOF;
}
fade->out_stop = samples;
if (!(truncate = !!fade->out_stop)) {
fade->out_stop = effp->in_signal.length != SOX_UNKNOWN_LEN ?
effp->in_signal.length / effp->in_signal.channels :
0;
if (!fade->out_stop) {
lsx_fail("cannot fade out: audio length is neither known nor given");
return SOX_EOF;
}
}
/* See if user wants to fade out. */
if (fade->out_start_str)
{
if (lsx_parsesamples(effp->in_signal.rate, fade->out_start_str,
&samples, 't') == NULL)
return lsx_usage(effp);
/* Fade time is relative to stop time. */
fade->out_start = fade->out_stop - samples;
}
else
/* If user doesn't specify fade out length then
* use same length as input side. This is stored
* in in_stop.
*/
fade->out_start = fade->out_stop - fade->in_stop;
}
else
/* If not specified then user wants to process all
* of file. Use a value of zero to indicate this.
*/
fade->out_stop = 0;
if (fade->out_start) { /* Sanity check */
if (fade->in_stop > fade->out_start)
--fade->in_stop; /* 1 sample grace for rounding error. */
if (fade->in_stop > fade->out_start) {
lsx_fail("fade-out overlaps fade-in");
return SOX_EOF;
}
}
fade->samplesdone = fade->in_start;
fade->endpadwarned = 0;
lsx_debug("in_start = %" PRIu64 " in_stop = %" PRIu64 " "
"out_start = %" PRIu64 " out_stop = %" PRIu64,
fade->in_start, fade->in_stop, fade->out_start, fade->out_stop);
if (fade->in_start == fade->in_stop && !truncate &&
fade->out_start == fade->out_stop)
return SOX_EFF_NULL;
effp->out_signal.length = truncate ?
fade->out_stop * effp->in_signal.channels : effp->in_signal.length;
return SOX_SUCCESS;
}
/*
* Processed signed long samples from ibuf to obuf.
* Return number of samples processed.
*/
static int sox_fade_flow(sox_effect_t * effp, const sox_sample_t *ibuf, sox_sample_t *obuf,
size_t *isamp, size_t *osamp)
{
priv_t * fade = (priv_t *) effp->priv;
/* len is total samples, chcnt counts channels */
int len = 0, t_output = 1, more_output = 1;
sox_sample_t t_ibuf;
size_t chcnt = 0;
len = ((*isamp > *osamp) ? *osamp : *isamp);
*osamp = 0;
*isamp = 0;
for(; len && more_output; len--)
{
t_ibuf = *ibuf;
if ((fade->samplesdone >= fade->in_start) &&
(!fade->do_out || fade->samplesdone < fade->out_stop))
{ /* something to generate output */
if (fade->samplesdone < fade->in_stop)
{ /* fade-in phase, increase gain */
*obuf = t_ibuf *
fade_gain(fade->samplesdone - fade->in_start,
fade->in_stop - fade->in_start,
fade->in_fadetype);
} /* endif fade-in */
else if (!fade->do_out || fade->samplesdone < fade->out_start)
{ /* steady gain phase */
*obuf = t_ibuf;
} /* endif steady phase */
else
{ /* fade-out phase, decrease gain */
*obuf = t_ibuf *
fade_gain(fade->out_stop - fade->samplesdone,
fade->out_stop - fade->out_start,
fade->out_fadetype);
} /* endif fade-out */
if (!(!fade->do_out || fade->samplesdone < fade->out_stop))
more_output = 0;
t_output = 1;
}
else
{ /* No output generated */
t_output = 0;
} /* endif something to output */
*isamp += 1;
ibuf++;
if (t_output)
{ /* Output generated, update pointers and counters */
obuf++;
*osamp += 1;
} /* endif t_output */
/* Process next channel */
chcnt++;
if (chcnt >= effp->in_signal.channels)
{ /* all channels of this sample processed */
chcnt = 0;
fade->samplesdone += 1;
} /* endif all channels */
} /* endfor */
/* If not more samples will be returned, let application know
* this.
*/
if (fade->do_out && fade->samplesdone >= fade->out_stop)
return SOX_EOF;
else
return SOX_SUCCESS;
}
/*
* Drain out remaining samples if the effect generates any.
*/
static int sox_fade_drain(sox_effect_t * effp, sox_sample_t *obuf, size_t *osamp)
{
priv_t * fade = (priv_t *) effp->priv;
int len;
size_t t_chan = 0;
len = *osamp;
len -= len % effp->in_signal.channels;
*osamp = 0;
if (fade->do_out && fade->samplesdone < fade->out_stop &&
!(fade->endpadwarned))
{ /* Warning about padding silence into end of sample */
lsx_warn("End time past end of audio. Padding with silence");
fade->endpadwarned = 1;
} /* endif endpadwarned */
for (;len && (fade->do_out &&
fade->samplesdone < fade->out_stop); len--)
{
*obuf = 0;
obuf++;
*osamp += 1;
t_chan++;
if (t_chan >= effp->in_signal.channels)
{
fade->samplesdone += 1;
t_chan = 0;
} /* endif channels */
} /* endfor */
if (fade->do_out && fade->samplesdone >= fade->out_stop)
return SOX_EOF;
else
return SOX_SUCCESS;
}
/*
* Do anything required when you stop reading samples.
* (free allocated memory, etc.)
*/
static int lsx_kill(sox_effect_t * effp)
{
priv_t * fade = (priv_t *) effp->priv;
free(fade->in_stop_str);
free(fade->out_start_str);
free(fade->out_stop_str);
return (SOX_SUCCESS);
}
/* Function returns gain value 0.0 - 1.0 according index / range ratio
* and -1.0 if type is invalid
* todo: to optimize performance calculate gain every now and then and interpolate */
static double fade_gain(uint64_t index, uint64_t range, int type)
{
double retval = 0.0, findex = 0.0;
/* TODO: does it really have to be contrained to [0.0, 1.0]? */
findex = max(0.0, min(1.0, 1.0 * index / range));
switch (type) {
case FADE_TRI : /* triangle */
retval = findex;
break;
case FADE_QUARTER : /* quarter of sinewave */
retval = sin(findex * M_PI / 2);
break;
case FADE_HALF : /* half of sinewave... eh cosine wave */
retval = (1 - cos(findex * M_PI )) / 2 ;
break;
case FADE_LOG : /* logarithmic */
/* 5 means 100 db attenuation. */
/* TODO: should this be adopted with bit depth */
retval = pow(0.1, (1 - findex) * 5);
break;
case FADE_PAR : /* inverted parabola */
retval = (1 - (1 - findex) * (1 - findex));
break;
/* TODO: more fade curves? */
default : /* Error indicating wrong fade curve */
retval = -1.0;
break;
}
return retval;
}
static sox_effect_handler_t sox_fade_effect = {
"fade",
"[ type ] fade-in-length [ stop-position [ fade-out-length ] ]\n"
" Time is in hh:mm:ss.frac format.\n"
" Fade type one of q, h, t, l or p.",
SOX_EFF_MCHAN | SOX_EFF_LENGTH,
sox_fade_getopts,
sox_fade_start,
sox_fade_flow,
sox_fade_drain,
NULL,
lsx_kill, sizeof(priv_t)
};
const sox_effect_handler_t *lsx_fade_effect_fn(void)
{
return &sox_fade_effect;
}

@ -1,31 +0,0 @@
/* libSoX file format: FAP 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"
LSX_FORMAT_HANDLER(fap)
{
static char const * const names[] = {"fap", NULL};
static unsigned const write_encodings[] = {SOX_ENCODING_SIGN2, 24, 16, 8,0,0};
static sox_format_handler_t handler;
handler = *lsx_sndfile_format_fn();
handler.description =
"Ensoniq PARIS digital audio editing system (little endian)";
handler.names = names;
handler.write_formats = write_encodings;
return &handler;
}

@ -1,105 +0,0 @@
/* Effect: fir filter from coefs Copyright (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 "dft_filter.h"
typedef struct {
dft_filter_priv_t base;
char const * filename;
double * h;
int n;
} priv_t;
static int create(sox_effect_t * effp, int argc, char * * argv)
{
priv_t * p = (priv_t *)effp->priv;
dft_filter_priv_t * b = &p->base;
double d;
char c;
b->filter_ptr = &b->filter;
--argc, ++argv;
if (!argc)
p->filename = "-"; /* default to stdin */
else if (argc == 1)
p->filename = argv[0], --argc;
else for (; argc && sscanf(*argv, "%lf%c", &d, &c) == 1; --argc, ++argv) {
p->n++;
p->h = lsx_realloc(p->h, p->n * sizeof(*p->h));
p->h[p->n - 1] = d;
}
return argc? lsx_usage(effp) : SOX_SUCCESS;
}
static int start(sox_effect_t * effp)
{
priv_t * p = (priv_t *)effp->priv;
dft_filter_t * f = p->base.filter_ptr;
double d;
char c;
int i;
if (!f->num_taps) {
if (!p->n && p->filename) {
FILE * file = lsx_open_input_file(effp, p->filename, sox_true);
if (!file)
return SOX_EOF;
while ((i = fscanf(file, " #%*[^\n]%c", &c)) >= 0) {
if (i >= 1) continue; /* found and skipped a comment */
if ((i = fscanf(file, "%lf", &d)) > 0) {
/* found a coefficient value */
p->n++;
p->h = lsx_realloc(p->h, p->n * sizeof(*p->h));
p->h[p->n - 1] = d;
} else break; /* either EOF, or something went wrong
(read or syntax error) */
}
if (!feof(file)) {
lsx_fail("error reading coefficient file");
if (file != stdin) fclose(file);
return SOX_EOF;
}
if (file != stdin) fclose(file);
}
lsx_report("%i coefficients", p->n);
if (!p->n)
return SOX_EFF_NULL;
if (effp->global_info->plot != sox_plot_off) {
char title[100];
sprintf(title, "SoX effect: fir (%d coefficients)", p->n);
lsx_plot_fir(p->h, p->n, effp->in_signal.rate,
effp->global_info->plot, title, -30., 30.);
free(p->h);
return SOX_EOF;
}
lsx_set_dft_filter(f, p->h, p->n, p->n >> 1);
}
return lsx_dft_filter_effect_fn()->start(effp);
}
sox_effect_handler_t const * lsx_fir_effect_fn(void)
{
static sox_effect_handler_t handler;
handler = *lsx_dft_filter_effect_fn();
handler.name = "fir";
handler.usage = "[coef-file|coefs]";
handler.getopts = create;
handler.start = start;
handler.priv_size = sizeof(priv_t);
return &handler;
}

@ -1,145 +0,0 @@
/* Effect: firfit filter Copyright (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
*/
/* This is W.I.P. hence marked SOX_EFF_ALPHA for now.
* Need to add other interpolation types e.g. linear, bspline, window types,
* and filter length, maybe phase response type too.
*/
#include "sox_i.h"
#include "dft_filter.h"
typedef struct {
dft_filter_priv_t base;
char const * filename;
struct {double f, gain;} * knots;
int num_knots, n;
} priv_t;
static int create(sox_effect_t * effp, int argc, char **argv)
{
priv_t * p = (priv_t *)effp->priv;
dft_filter_priv_t * b = &p->base;
b->filter_ptr = &b->filter;
--argc, ++argv;
if (argc == 1)
p->filename = argv[0], --argc;
p->n = 2047;
return argc? lsx_usage(effp) : SOX_SUCCESS;
}
static double * make_filter(sox_effect_t * effp)
{
priv_t * p = (priv_t *)effp->priv;
double * log_freqs, * gains, * d, * work, * h;
sox_rate_t rate = effp->in_signal.rate;
int i, work_len;
lsx_valloc(log_freqs , p->num_knots);
lsx_valloc(gains, p->num_knots);
lsx_valloc(d , p->num_knots);
for (i = 0; i < p->num_knots; ++i) {
log_freqs[i] = log(max(p->knots[i].f, 1));
gains[i] = p->knots[i].gain;
}
lsx_prepare_spline3(log_freqs, gains, p->num_knots, HUGE_VAL, HUGE_VAL, d);
for (work_len = 8192; work_len < rate / 2; work_len <<= 1);
work = lsx_calloc(work_len + 2, sizeof(*work));
lsx_valloc(h, p->n);
for (i = 0; i <= work_len; i += 2) {
double f = rate * 0.5 * i / work_len;
double spl1 = f < max(p->knots[0].f, 1)? gains[0] :
f > p->knots[p->num_knots - 1].f? gains[p->num_knots - 1] :
lsx_spline3(log_freqs, gains, d, p->num_knots, log(f));
work[i] = dB_to_linear(spl1);
}
LSX_PACK(work, work_len);
lsx_safe_rdft(work_len, -1, work);
for (i = 0; i < p->n; ++i)
h[i] = work[(work_len - p->n / 2 + i) % work_len] * 2. / work_len;
lsx_apply_blackman_nutall(h, p->n);
free(work);
return h;
}
static sox_bool read_knots(sox_effect_t * effp)
{
priv_t * p = (priv_t *) effp->priv;
FILE * file = lsx_open_input_file(effp, p->filename, sox_true);
sox_bool result = sox_false;
int num_converted = 1;
char c;
if (file) {
lsx_valloc(p->knots, 1);
while (fscanf(file, " #%*[^\n]%c", &c) >= 0) {
num_converted = fscanf(file, "%lf %lf",
&p->knots[p->num_knots].f, &p->knots[p->num_knots].gain);
if (num_converted == 2) {
if (p->num_knots && p->knots[p->num_knots].f <= p->knots[p->num_knots - 1].f) {
lsx_fail("knot frequencies must be strictly increasing");
break;
}
lsx_revalloc(p->knots, ++p->num_knots + 1);
} else if (num_converted != 0)
break;
}
lsx_report("%i knots", p->num_knots);
if (feof(file) && num_converted != 1)
result = sox_true;
else lsx_fail("error reading knot file `%s', line number %u", p->filename, 1 + p->num_knots);
if (file != stdin)
fclose(file);
}
return result;
}
static int start(sox_effect_t * effp)
{
priv_t * p = (priv_t *) effp->priv;
dft_filter_t * f = p->base.filter_ptr;
if (!f->num_taps) {
double * h;
if (!p->num_knots && !read_knots(effp))
return SOX_EOF;
h = make_filter(effp);
if (effp->global_info->plot != sox_plot_off) {
lsx_plot_fir(h, p->n, effp->in_signal.rate,
effp->global_info->plot, "SoX effect: firfit", -30., +30.);
return SOX_EOF;
}
lsx_set_dft_filter(f, h, p->n, p->n >> 1);
}
return lsx_dft_filter_effect_fn()->start(effp);
}
sox_effect_handler_t const * lsx_firfit_effect_fn(void)
{
static sox_effect_handler_t handler;
handler = *lsx_dft_filter_effect_fn();
handler.name = "firfit";
handler.usage = "[knots-file]";
handler.flags |= SOX_EFF_ALPHA;
handler.getopts = create;
handler.start = start;
handler.priv_size = sizeof(priv_t);
return &handler;
}

@ -1,606 +0,0 @@
/* libSoX file format: FLAC (c) 2006-7 robs@users.sourceforge.net
*
* This library is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation; either version 2.1 of the License, or (at
* your option) any later version.
*
* This library is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser
* General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this library; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "sox_i.h"
#include <string.h>
/* Next line for systems that don't define off_t when you #include
stdio.h; apparently OS/2 has this bug */
#include <sys/types.h>
#include <FLAC/all.h>
#define MAX_COMPRESSION 8
typedef struct {
/* Info: */
unsigned bits_per_sample;
unsigned channels;
unsigned sample_rate;
uint64_t total_samples;
/* Decode buffer: */
sox_sample_t *req_buffer; /* this may be on the stack */
size_t number_of_requested_samples;
sox_sample_t *leftover_buf; /* heap */
unsigned number_of_leftover_samples;
FLAC__StreamDecoder * decoder;
FLAC__bool eof;
sox_bool seek_pending;
uint64_t seek_offset;
/* Encode buffer: */
FLAC__int32 * decoded_samples;
unsigned number_of_samples;
FLAC__StreamEncoder * encoder;
FLAC__StreamMetadata * metadata[2];
unsigned num_metadata;
} priv_t;
static FLAC__StreamDecoderReadStatus decoder_read_callback(FLAC__StreamDecoder const* decoder UNUSED, FLAC__byte buffer[], size_t* bytes, void* ft_data)
{
sox_format_t* ft = (sox_format_t*)ft_data;
if(*bytes > 0) {
*bytes = lsx_readbuf(ft, buffer, *bytes);
if(lsx_error(ft))
return FLAC__STREAM_DECODER_READ_STATUS_ABORT;
else if(*bytes == 0)
return FLAC__STREAM_DECODER_READ_STATUS_END_OF_STREAM;
else
return FLAC__STREAM_DECODER_READ_STATUS_CONTINUE;
}
else
return FLAC__STREAM_DECODER_READ_STATUS_ABORT;
}
static FLAC__StreamDecoderSeekStatus decoder_seek_callback(FLAC__StreamDecoder const* decoder UNUSED, FLAC__uint64 absolute_byte_offset, void* ft_data)
{
sox_format_t* ft = (sox_format_t*)ft_data;
if(lsx_seeki(ft, (off_t)absolute_byte_offset, SEEK_SET) < 0)
return FLAC__STREAM_DECODER_SEEK_STATUS_ERROR;
else
return FLAC__STREAM_DECODER_SEEK_STATUS_OK;
}
static FLAC__StreamDecoderTellStatus decoder_tell_callback(FLAC__StreamDecoder const* decoder UNUSED, FLAC__uint64* absolute_byte_offset, void* ft_data)
{
sox_format_t* ft = (sox_format_t*)ft_data;
off_t pos;
if((pos = lsx_tell(ft)) < 0)
return FLAC__STREAM_DECODER_TELL_STATUS_ERROR;
else {
*absolute_byte_offset = (FLAC__uint64)pos;
return FLAC__STREAM_DECODER_TELL_STATUS_OK;
}
}
static FLAC__StreamDecoderLengthStatus decoder_length_callback(FLAC__StreamDecoder const* decoder UNUSED, FLAC__uint64* stream_length, void* ft_data)
{
sox_format_t* ft = (sox_format_t*)ft_data;
*stream_length = lsx_filelength(ft);
return FLAC__STREAM_DECODER_LENGTH_STATUS_OK;
}
static FLAC__bool decoder_eof_callback(FLAC__StreamDecoder const* decoder UNUSED, void* ft_data)
{
sox_format_t* ft = (sox_format_t*)ft_data;
return lsx_eof(ft) ? 1 : 0;
}
static void decoder_metadata_callback(FLAC__StreamDecoder const * const flac, FLAC__StreamMetadata const * const metadata, void * const client_data)
{
sox_format_t * ft = (sox_format_t *) client_data;
priv_t * p = (priv_t *)ft->priv;
(void) flac;
if (metadata->type == FLAC__METADATA_TYPE_STREAMINFO) {
p->bits_per_sample = metadata->data.stream_info.bits_per_sample;
p->channels = metadata->data.stream_info.channels;
p->sample_rate = metadata->data.stream_info.sample_rate;
p->total_samples = metadata->data.stream_info.total_samples;
}
else if (metadata->type == FLAC__METADATA_TYPE_VORBIS_COMMENT) {
const FLAC__StreamMetadata_VorbisComment *vc = &metadata->data.vorbis_comment;
size_t i;
if (vc->num_comments == 0)
return;
if (ft->oob.comments != NULL) {
lsx_warn("multiple Vorbis comment block ignored");
return;
}
for (i = 0; i < vc->num_comments; ++i)
if (vc->comments[i].entry)
sox_append_comment(&ft->oob.comments, (char const *) vc->comments[i].entry);
}
}
static void decoder_error_callback(FLAC__StreamDecoder const * const flac, FLAC__StreamDecoderErrorStatus const status, void * const client_data)
{
sox_format_t * ft = (sox_format_t *) client_data;
(void) flac;
lsx_fail_errno(ft, SOX_EINVAL, "%s", FLAC__StreamDecoderErrorStatusString[status]);
}
static FLAC__StreamDecoderWriteStatus decoder_write_callback(FLAC__StreamDecoder const * const flac, FLAC__Frame const * const frame, FLAC__int32 const * const buffer[], void * const client_data)
{
sox_format_t * ft = (sox_format_t *) client_data;
priv_t * p = (priv_t *)ft->priv;
sox_sample_t * dst = p->req_buffer;
unsigned channel;
unsigned nsamples = frame->header.blocksize;
unsigned sample = 0;
size_t actual = nsamples * p->channels;
(void) flac;
if (frame->header.bits_per_sample != p->bits_per_sample || frame->header.channels != p->channels || frame->header.sample_rate != p->sample_rate) {
lsx_fail_errno(ft, SOX_EINVAL, "FLAC ERROR: parameters differ between frame and header");
return FLAC__STREAM_DECODER_WRITE_STATUS_ABORT;
}
if (dst == NULL) {
lsx_warn("FLAC ERROR: entered write callback without a buffer (SoX bug)");
return FLAC__STREAM_DECODER_WRITE_STATUS_ABORT;
}
/* FLAC may give us too much data, prepare the leftover buffer */
if (actual > p->number_of_requested_samples) {
size_t to_stash = actual - p->number_of_requested_samples;
p->leftover_buf = lsx_malloc(to_stash * sizeof(sox_sample_t));
p->number_of_leftover_samples = to_stash;
nsamples = p->number_of_requested_samples / p->channels;
p->req_buffer += p->number_of_requested_samples;
p->number_of_requested_samples = 0;
} else {
p->req_buffer += actual;
p->number_of_requested_samples -= actual;
}
leftover_copy:
for (; sample < nsamples; sample++) {
for (channel = 0; channel < p->channels; channel++) {
FLAC__int32 d = buffer[channel][sample];
switch (p->bits_per_sample) {
case 8: *dst++ = SOX_SIGNED_8BIT_TO_SAMPLE(d,); break;
case 16: *dst++ = SOX_SIGNED_16BIT_TO_SAMPLE(d,); break;
case 24: *dst++ = SOX_SIGNED_24BIT_TO_SAMPLE(d,); break;
case 32: *dst++ = SOX_SIGNED_32BIT_TO_SAMPLE(d,); break;
}
}
}
/* copy into the leftover buffer if we've prepared it */
if (sample < frame->header.blocksize) {
nsamples = frame->header.blocksize;
dst = p->leftover_buf;
goto leftover_copy;
}
return FLAC__STREAM_DECODER_WRITE_STATUS_CONTINUE;
}
static int start_read(sox_format_t * const ft)
{
priv_t * p = (priv_t *)ft->priv;
lsx_debug("API version %u", FLAC_API_VERSION_CURRENT);
p->decoder = FLAC__stream_decoder_new();
if (p->decoder == NULL) {
lsx_fail_errno(ft, SOX_ENOMEM, "FLAC ERROR creating the decoder instance");
return SOX_EOF;
}
FLAC__stream_decoder_set_md5_checking(p->decoder, sox_true);
FLAC__stream_decoder_set_metadata_respond_all(p->decoder);
if (FLAC__stream_decoder_init_stream(
p->decoder,
decoder_read_callback,
ft->seekable ? decoder_seek_callback : NULL,
ft->seekable ? decoder_tell_callback : NULL,
ft->seekable ? decoder_length_callback : NULL,
ft->seekable ? decoder_eof_callback : NULL,
decoder_write_callback,
decoder_metadata_callback,
decoder_error_callback,
ft) != FLAC__STREAM_DECODER_INIT_STATUS_OK){
lsx_fail_errno(ft, SOX_EHDR, "FLAC ERROR initialising decoder");
return SOX_EOF;
}
if (!FLAC__stream_decoder_process_until_end_of_metadata(p->decoder)) {
lsx_fail_errno(ft, SOX_EHDR, "FLAC ERROR whilst decoding metadata");
return SOX_EOF;
}
if (FLAC__stream_decoder_get_state(p->decoder) > FLAC__STREAM_DECODER_END_OF_STREAM) {
lsx_fail_errno(ft, SOX_EHDR, "FLAC ERROR during metadata decoding");
return SOX_EOF;
}
ft->encoding.encoding = SOX_ENCODING_FLAC;
ft->signal.rate = p->sample_rate;
ft->encoding.bits_per_sample = p->bits_per_sample;
ft->signal.channels = p->channels;
ft->signal.length = p->total_samples * p->channels;
return SOX_SUCCESS;
}
static size_t read_samples(sox_format_t * const ft, sox_sample_t * sampleBuffer, size_t const requested)
{
priv_t * p = (priv_t *)ft->priv;
size_t prev_requested;
if (p->seek_pending) {
p->seek_pending = sox_false;
/* discard leftover decoded data */
free(p->leftover_buf);
p->leftover_buf = NULL;
p->number_of_leftover_samples = 0;
p->req_buffer = sampleBuffer;
p->number_of_requested_samples = requested;
/* calls decoder_write_callback */
if (!FLAC__stream_decoder_seek_absolute(p->decoder, (FLAC__uint64)(p->seek_offset / ft->signal.channels))) {
p->req_buffer = NULL;
return 0;
}
} else if (p->number_of_leftover_samples > 0) {
/* small request, no need to decode more samples since we have leftovers */
if (requested < p->number_of_leftover_samples) {
size_t req_bytes = requested * sizeof(sox_sample_t);
memcpy(sampleBuffer, p->leftover_buf, req_bytes);
p->number_of_leftover_samples -= requested;
memmove(p->leftover_buf, (char *)p->leftover_buf + req_bytes,
(size_t)p->number_of_leftover_samples * sizeof(sox_sample_t));
return requested;
}
/* first, give them all of our leftover data: */
memcpy(sampleBuffer, p->leftover_buf,
p->number_of_leftover_samples * sizeof(sox_sample_t));
p->req_buffer = sampleBuffer + p->number_of_leftover_samples;
p->number_of_requested_samples = requested - p->number_of_leftover_samples;
free(p->leftover_buf);
p->leftover_buf = NULL;
p->number_of_leftover_samples = 0;
/* continue invoking decoder below */
} else {
p->req_buffer = sampleBuffer;
p->number_of_requested_samples = requested;
}
/* invoke the decoder, calls decoder_write_callback */
while ((prev_requested = p->number_of_requested_samples) && !p->eof) {
if (!FLAC__stream_decoder_process_single(p->decoder))
break; /* error, but maybe got earlier in the loop, though */
/* number_of_requested_samples decrements as the decoder progresses */
if (p->number_of_requested_samples == prev_requested)
p->eof = sox_true;
}
p->req_buffer = NULL;
return requested - p->number_of_requested_samples;
}
static int stop_read(sox_format_t * const ft)
{
priv_t * p = (priv_t *)ft->priv;
if (!FLAC__stream_decoder_finish(p->decoder) && p->eof)
lsx_warn("decoder MD5 checksum mismatch.");
FLAC__stream_decoder_delete(p->decoder);
free(p->leftover_buf);
p->leftover_buf = NULL;
p->number_of_leftover_samples = 0;
return SOX_SUCCESS;
}
static FLAC__StreamEncoderWriteStatus flac_stream_encoder_write_callback(FLAC__StreamEncoder const * const flac, const FLAC__byte buffer[], size_t const bytes, unsigned const samples, unsigned const current_frame, void * const client_data)
{
sox_format_t * const ft = (sox_format_t *) client_data;
(void) flac, (void) samples, (void) current_frame;
return lsx_writebuf(ft, buffer, bytes) == bytes ? FLAC__STREAM_ENCODER_WRITE_STATUS_OK : FLAC__STREAM_ENCODER_WRITE_STATUS_FATAL_ERROR;
}
static void flac_stream_encoder_metadata_callback(FLAC__StreamEncoder const * encoder, FLAC__StreamMetadata const * metadata, void * client_data)
{
(void) encoder, (void) metadata, (void) client_data;
}
static FLAC__StreamEncoderSeekStatus flac_stream_encoder_seek_callback(FLAC__StreamEncoder const * encoder, FLAC__uint64 absolute_byte_offset, void * client_data)
{
sox_format_t * const ft = (sox_format_t *) client_data;
(void) encoder;
if (!ft->seekable)
return FLAC__STREAM_ENCODER_SEEK_STATUS_UNSUPPORTED;
else if (lsx_seeki(ft, (off_t)absolute_byte_offset, SEEK_SET) != SOX_SUCCESS)
return FLAC__STREAM_ENCODER_SEEK_STATUS_ERROR;
else
return FLAC__STREAM_ENCODER_SEEK_STATUS_OK;
}
static FLAC__StreamEncoderTellStatus flac_stream_encoder_tell_callback(FLAC__StreamEncoder const * encoder, FLAC__uint64 * absolute_byte_offset, void * client_data)
{
sox_format_t * const ft = (sox_format_t *) client_data;
off_t pos;
(void) encoder;
if (!ft->seekable)
return FLAC__STREAM_ENCODER_TELL_STATUS_UNSUPPORTED;
else if ((pos = lsx_tell(ft)) < 0)
return FLAC__STREAM_ENCODER_TELL_STATUS_ERROR;
else {
*absolute_byte_offset = (FLAC__uint64)pos;
return FLAC__STREAM_ENCODER_TELL_STATUS_OK;
}
}
static int start_write(sox_format_t * const ft)
{
priv_t * p = (priv_t *)ft->priv;
FLAC__StreamEncoderInitStatus status;
unsigned compression_level = MAX_COMPRESSION; /* Default to "best" */
if (ft->encoding.compression != HUGE_VAL) {
compression_level = ft->encoding.compression;
if (compression_level != ft->encoding.compression ||
compression_level > MAX_COMPRESSION) {
lsx_fail_errno(ft, SOX_EINVAL,
"FLAC compression level must be a whole number from 0 to %i",
MAX_COMPRESSION);
return SOX_EOF;
}
}
p->encoder = FLAC__stream_encoder_new();
if (p->encoder == NULL) {
lsx_fail_errno(ft, SOX_ENOMEM, "FLAC ERROR creating the encoder instance");
return SOX_EOF;
}
p->bits_per_sample = ft->encoding.bits_per_sample;
ft->signal.precision = ft->encoding.bits_per_sample;
lsx_report("encoding at %i bits per sample", p->bits_per_sample);
FLAC__stream_encoder_set_channels(p->encoder, ft->signal.channels);
FLAC__stream_encoder_set_bits_per_sample(p->encoder, p->bits_per_sample);
FLAC__stream_encoder_set_sample_rate(p->encoder, (unsigned)(ft->signal.rate + .5));
{ /* Check if rate is streamable: */
static const unsigned streamable_rates[] =
{8000, 16000, 22050, 24000, 32000, 44100, 48000, 96000};
size_t i;
sox_bool streamable = sox_false;
for (i = 0; !streamable && i < array_length(streamable_rates); ++i)
streamable = (streamable_rates[i] == ft->signal.rate);
if (!streamable) {
lsx_report("non-standard rate; output may not be streamable");
FLAC__stream_encoder_set_streamable_subset(p->encoder, sox_false);
}
}
#if FLAC_API_VERSION_CURRENT >= 10
FLAC__stream_encoder_set_compression_level(p->encoder, compression_level);
#else
{
static struct {
unsigned blocksize;
FLAC__bool do_exhaustive_model_search;
FLAC__bool do_mid_side_stereo;
FLAC__bool loose_mid_side_stereo;
unsigned max_lpc_order;
unsigned max_residual_partition_order;
unsigned min_residual_partition_order;
} const options[MAX_COMPRESSION + 1] = {
{1152, sox_false, sox_false, sox_false, 0, 2, 2},
{1152, sox_false, sox_true, sox_true, 0, 2, 2},
{1152, sox_false, sox_true, sox_false, 0, 3, 0},
{4608, sox_false, sox_false, sox_false, 6, 3, 3},
{4608, sox_false, sox_true, sox_true, 8, 3, 3},
{4608, sox_false, sox_true, sox_false, 8, 3, 3},
{4608, sox_false, sox_true, sox_false, 8, 4, 0},
{4608, sox_true, sox_true, sox_false, 8, 6, 0},
{4608, sox_true, sox_true, sox_false, 12, 6, 0},
};
#define SET_OPTION(x) do {\
lsx_report(#x" = %i", options[compression_level].x); \
FLAC__stream_encoder_set_##x(p->encoder, options[compression_level].x);\
} while (0)
SET_OPTION(blocksize);
SET_OPTION(do_exhaustive_model_search);
SET_OPTION(max_lpc_order);
SET_OPTION(max_residual_partition_order);
SET_OPTION(min_residual_partition_order);
if (ft->signal.channels == 2) {
SET_OPTION(do_mid_side_stereo);
SET_OPTION(loose_mid_side_stereo);
}
#undef SET_OPTION
}
#endif
if (ft->signal.length != 0) {
FLAC__stream_encoder_set_total_samples_estimate(p->encoder, (FLAC__uint64)(ft->signal.length / ft->signal.channels));
p->metadata[p->num_metadata] = FLAC__metadata_object_new(FLAC__METADATA_TYPE_SEEKTABLE);
if (p->metadata[p->num_metadata] == NULL) {
lsx_fail_errno(ft, SOX_ENOMEM, "FLAC ERROR creating the encoder seek table template");
return SOX_EOF;
}
{
if (!FLAC__metadata_object_seektable_template_append_spaced_points_by_samples(p->metadata[p->num_metadata], (unsigned)(10 * ft->signal.rate + .5), (FLAC__uint64)(ft->signal.length/ft->signal.channels))) {
lsx_fail_errno(ft, SOX_ENOMEM, "FLAC ERROR creating the encoder seek table points");
return SOX_EOF;
}
}
p->metadata[p->num_metadata]->is_last = sox_false; /* the encoder will set this for us */
++p->num_metadata;
}
if (ft->oob.comments) { /* Make the comment structure */
FLAC__StreamMetadata_VorbisComment_Entry entry;
int i;
p->metadata[p->num_metadata] = FLAC__metadata_object_new(FLAC__METADATA_TYPE_VORBIS_COMMENT);
for (i = 0; ft->oob.comments[i]; ++i) {
static const char prepend[] = "Comment=";
char * text = lsx_calloc(strlen(prepend) + strlen(ft->oob.comments[i]) + 1, sizeof(*text));
/* Prepend `Comment=' if no field-name already in the comment */
if (!strchr(ft->oob.comments[i], '='))
strcpy(text, prepend);
entry.entry = (FLAC__byte *) strcat(text, ft->oob.comments[i]);
entry.length = strlen(text);
FLAC__metadata_object_vorbiscomment_append_comment(p->metadata[p->num_metadata], entry, /*copy= */ sox_true);
free(text);
}
++p->num_metadata;
}
if (p->num_metadata)
FLAC__stream_encoder_set_metadata(p->encoder, p->metadata, p->num_metadata);
status = FLAC__stream_encoder_init_stream(p->encoder, flac_stream_encoder_write_callback,
flac_stream_encoder_seek_callback, flac_stream_encoder_tell_callback, flac_stream_encoder_metadata_callback, ft);
if (status != FLAC__STREAM_ENCODER_INIT_STATUS_OK) {
lsx_fail_errno(ft, SOX_EINVAL, "%s", FLAC__StreamEncoderInitStatusString[status]);
return SOX_EOF;
}
return SOX_SUCCESS;
}
static size_t write_samples(sox_format_t * const ft, sox_sample_t const * const sampleBuffer, size_t const len)
{
priv_t * p = (priv_t *)ft->priv;
unsigned i;
/* allocate or grow buffer */
if (p->number_of_samples < len) {
p->number_of_samples = len;
free(p->decoded_samples);
p->decoded_samples = lsx_malloc(p->number_of_samples * sizeof(FLAC__int32));
}
for (i = 0; i < len; ++i) {
SOX_SAMPLE_LOCALS;
long pcm = SOX_SAMPLE_TO_SIGNED_32BIT(sampleBuffer[i], ft->clips);
p->decoded_samples[i] = pcm >> (32 - p->bits_per_sample);
switch (p->bits_per_sample) {
case 8: p->decoded_samples[i] =
SOX_SAMPLE_TO_SIGNED_8BIT(sampleBuffer[i], ft->clips);
break;
case 16: p->decoded_samples[i] =
SOX_SAMPLE_TO_SIGNED_16BIT(sampleBuffer[i], ft->clips);
break;
case 24: p->decoded_samples[i] = /* sign extension: */
SOX_SAMPLE_TO_SIGNED_24BIT(sampleBuffer[i],ft->clips) << 8;
p->decoded_samples[i] >>= 8;
break;
case 32: p->decoded_samples[i] =
SOX_SAMPLE_TO_SIGNED_32BIT(sampleBuffer[i],ft->clips);
break;
}
}
FLAC__stream_encoder_process_interleaved(p->encoder, p->decoded_samples, (unsigned) len / ft->signal.channels);
return FLAC__stream_encoder_get_state(p->encoder) == FLAC__STREAM_ENCODER_OK ? len : 0;
}
static int stop_write(sox_format_t * const ft)
{
priv_t * p = (priv_t *)ft->priv;
FLAC__StreamEncoderState state = FLAC__stream_encoder_get_state(p->encoder);
unsigned i;
FLAC__stream_encoder_finish(p->encoder);
FLAC__stream_encoder_delete(p->encoder);
for (i = 0; i < p->num_metadata; ++i)
FLAC__metadata_object_delete(p->metadata[i]);
free(p->decoded_samples);
if (state != FLAC__STREAM_ENCODER_OK) {
lsx_fail_errno(ft, SOX_EINVAL, "FLAC ERROR: failed to encode to end of stream");
return SOX_EOF;
}
return SOX_SUCCESS;
}
static int seek(sox_format_t * ft, uint64_t offset)
{
priv_t * p = (priv_t *)ft->priv;
p->seek_offset = offset;
p->seek_pending = sox_true;
return ft->mode == 'r' ? SOX_SUCCESS : SOX_EOF;
}
LSX_FORMAT_HANDLER(flac)
{
static char const * const names[] = {"flac", NULL};
static unsigned const encodings[] = {SOX_ENCODING_FLAC, 8, 16, 24, 0, 0};
static sox_format_handler_t const handler = {SOX_LIB_VERSION_CODE,
"Free Lossless Audio CODEC compressed audio", names, 0,
start_read, read_samples, stop_read,
start_write, write_samples, stop_write,
seek, encodings, NULL, sizeof(priv_t)
};
return &handler;
}

@ -1,275 +0,0 @@
/* libSoX effect: Stereo Flanger (c) 2006 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
*/
/* TODO: Slide in the delay at the start? */
#include "sox_i.h"
#include <string.h>
typedef enum {INTERP_LINEAR, INTERP_QUADRATIC} interp_t;
#define MAX_CHANNELS 4
typedef struct {
/* Parameters */
double delay_min;
double delay_depth;
double feedback_gain;
double delay_gain;
double speed;
lsx_wave_t wave_shape;
double channel_phase;
interp_t interpolation;
/* Delay buffers */
double * delay_bufs[MAX_CHANNELS];
size_t delay_buf_length;
size_t delay_buf_pos;
double delay_last[MAX_CHANNELS];
/* Low Frequency Oscillator */
float * lfo;
size_t lfo_length;
size_t lfo_pos;
/* Balancing */
double in_gain;
} priv_t;
static lsx_enum_item const interp_enum[] = {
LSX_ENUM_ITEM(INTERP_,LINEAR)
LSX_ENUM_ITEM(INTERP_,QUADRATIC)
{0, 0}};
static int getopts(sox_effect_t * effp, int argc, char *argv[])
{
priv_t * p = (priv_t *) effp->priv;
--argc, ++argv;
/* Set non-zero defaults: */
p->delay_depth = 2;
p->delay_gain = 71;
p->speed = 0.5;
p->channel_phase= 25;
do { /* break-able block */
NUMERIC_PARAMETER(delay_min , 0 , 30 )
NUMERIC_PARAMETER(delay_depth , 0 , 10 )
NUMERIC_PARAMETER(feedback_gain,-95 , 95 )
NUMERIC_PARAMETER(delay_gain , 0 , 100)
NUMERIC_PARAMETER(speed , 0.1, 10 )
TEXTUAL_PARAMETER(wave_shape, lsx_get_wave_enum())
NUMERIC_PARAMETER(channel_phase, 0 , 100)
TEXTUAL_PARAMETER(interpolation, interp_enum)
} while (0);
if (argc != 0)
return lsx_usage(effp);
lsx_report("parameters:\n"
"delay = %gms\n"
"depth = %gms\n"
"regen = %g%%\n"
"width = %g%%\n"
"speed = %gHz\n"
"shape = %s\n"
"phase = %g%%\n"
"interp= %s",
p->delay_min,
p->delay_depth,
p->feedback_gain,
p->delay_gain,
p->speed,
lsx_get_wave_enum()[p->wave_shape].text,
p->channel_phase,
interp_enum[p->interpolation].text);
/* Scale to unity: */
p->feedback_gain /= 100;
p->delay_gain /= 100;
p->channel_phase /= 100;
p->delay_min /= 1000;
p->delay_depth /= 1000;
return SOX_SUCCESS;
}
static int start(sox_effect_t * effp)
{
priv_t * f = (priv_t *) effp->priv;
int c, channels = effp->in_signal.channels;
if (channels > MAX_CHANNELS) {
lsx_fail("Can not operate with more than %i channels", MAX_CHANNELS);
return SOX_EOF;
}
/* Balance output: */
f->in_gain = 1 / (1 + f->delay_gain);
f->delay_gain /= 1 + f->delay_gain;
/* Balance feedback loop: */
f->delay_gain *= 1 - fabs(f->feedback_gain);
lsx_debug("in_gain=%g feedback_gain=%g delay_gain=%g\n",
f->in_gain, f->feedback_gain, f->delay_gain);
/* Create the delay buffers, one for each channel: */
f->delay_buf_length =
(f->delay_min + f->delay_depth) * effp->in_signal.rate + 0.5;
++f->delay_buf_length; /* Need 0 to n, i.e. n + 1. */
++f->delay_buf_length; /* Quadratic interpolator needs one more. */
for (c = 0; c < channels; ++c)
f->delay_bufs[c] = lsx_calloc(f->delay_buf_length, sizeof(*f->delay_bufs[0]));
/* Create the LFO lookup table: */
f->lfo_length = effp->in_signal.rate / f->speed;
f->lfo = lsx_calloc(f->lfo_length, sizeof(*f->lfo));
lsx_generate_wave_table(
f->wave_shape,
SOX_FLOAT,
f->lfo,
f->lfo_length,
floor(f->delay_min * effp->in_signal.rate + .5),
f->delay_buf_length - 2.,
3 * M_PI_2); /* Start the sweep at minimum delay (for mono at least) */
lsx_debug("delay_buf_length=%" PRIuPTR " lfo_length=%" PRIuPTR "\n",
f->delay_buf_length, f->lfo_length);
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 * f = (priv_t *) effp->priv;
int c, channels = effp->in_signal.channels;
size_t len = (*isamp > *osamp ? *osamp : *isamp) / channels;
*isamp = *osamp = len * channels;
while (len--) {
f->delay_buf_pos =
(f->delay_buf_pos + f->delay_buf_length - 1) % f->delay_buf_length;
for (c = 0; c < channels; ++c) {
double delayed_0, delayed_1;
double delayed;
double in, out;
size_t channel_phase = c * f->lfo_length * f->channel_phase + .5;
double delay = f->lfo[(f->lfo_pos + channel_phase) % f->lfo_length];
double frac_delay = modf(delay, &delay);
size_t int_delay = (size_t)delay;
in = *ibuf++;
f->delay_bufs[c][f->delay_buf_pos] = in + f->delay_last[c] * f->feedback_gain;
delayed_0 = f->delay_bufs[c]
[(f->delay_buf_pos + int_delay++) % f->delay_buf_length];
delayed_1 = f->delay_bufs[c]
[(f->delay_buf_pos + int_delay++) % f->delay_buf_length];
if (f->interpolation == INTERP_LINEAR)
delayed = delayed_0 + (delayed_1 - delayed_0) * frac_delay;
else /* if (f->interpolation == INTERP_QUADRATIC) */
{
double a, b;
double delayed_2 = f->delay_bufs[c]
[(f->delay_buf_pos + int_delay++) % f->delay_buf_length];
delayed_2 -= delayed_0;
delayed_1 -= delayed_0;
a = delayed_2 *.5 - delayed_1;
b = delayed_1 * 2 - delayed_2 *.5;
delayed = delayed_0 + (a * frac_delay + b) * frac_delay;
}
f->delay_last[c] = delayed;
out = in * f->in_gain + delayed * f->delay_gain;
*obuf++ = SOX_ROUND_CLIP_COUNT(out, effp->clips);
}
f->lfo_pos = (f->lfo_pos + 1) % f->lfo_length;
}
return SOX_SUCCESS;
}
static int stop(sox_effect_t * effp)
{
priv_t * f = (priv_t *) effp->priv;
int c, channels = effp->in_signal.channels;
for (c = 0; c < channels; ++c)
free(f->delay_bufs[c]);
free(f->lfo);
memset(f, 0, sizeof(*f));
return SOX_SUCCESS;
}
sox_effect_handler_t const * lsx_flanger_effect_fn(void)
{
static sox_effect_handler_t handler = {
"flanger", NULL, SOX_EFF_MCHAN,
getopts, start, flow, NULL, stop, NULL, sizeof(priv_t)};
static char const * lines[] = {
"[delay depth regen width speed shape phase interp]",
" .",
" /|regen",
" / |",
" +--( |------------+",
" | \\ | | .",
" _V_ \\| _______ | |\\ width ___",
" | | ' | | | | \\ | |",
" +-->| + |---->| DELAY |--+-->| )----->| |",
" | |___| |_______| | / | |",
" | delay : depth |/ | |",
" In | : interp ' | | Out",
" --->+ __:__ | + |--->",
" | | |speed | |",
" | | ~ |shape | |",
" | |_____|phase | |",
" +------------------------------------->| |",
" |___|",
" RANGE DEFAULT DESCRIPTION",
"delay 0 30 0 base delay in milliseconds",
"depth 0 10 2 added swept delay in milliseconds",
"regen -95 +95 0 percentage regeneration (delayed signal feedback)",
"width 0 100 71 percentage of delayed signal mixed with original",
"speed 0.1 10 0.5 sweeps per second (Hz) ",
"shape -- sin swept wave shape: sine|triangle",
"phase 0 100 25 swept wave percentage phase-shift for multi-channel",
" (e.g. stereo) flange; 0 = 100 = same phase on each channel",
"interp -- lin delay-line interpolation: linear|quadratic"
};
static char * usage;
handler.usage = lsx_usage_lines(&usage, lines, array_length(lines));
return &handler;
}

@ -19,7 +19,7 @@
// FORMAT(aifc)
// FORMAT(aiff)
FORMAT(al)
// FORMAT(al)
// FORMAT(au)
// FORMAT(avr)
// FORMAT(cdr)
@ -27,38 +27,38 @@
// FORMAT(cvu)
// FORMAT(dat)
// FORMAT(dvms)
FORMAT(f4)
FORMAT(f8)
// FORMAT(f4)
// FORMAT(f8)
// FORMAT(gsrt)
// FORMAT(hcom)
// FORMAT(htk)
FORMAT(ima)
FORMAT(la)
FORMAT(lu)
// FORMAT(ima)
// FORMAT(la)
// FORMAT(lu)
// FORMAT(maud)
// FORMAT(nul)
// FORMAT(prc)
FORMAT(raw)
FORMAT(s1)
FORMAT(s2)
FORMAT(s3)
FORMAT(s4)
// FORMAT(raw)
// FORMAT(s1)
// FORMAT(s2)
// FORMAT(s3)
// FORMAT(s4)
// FORMAT(sf)
FORMAT(sln)
// FORMAT(sln)
// FORMAT(smp)
// FORMAT(sounder)
// FORMAT(soundtool)
FORMAT(sox)
// FORMAT(sox)
// FORMAT(sphere)
// FORMAT(svx)
// FORMAT(txw)
FORMAT(u1)
FORMAT(u2)
FORMAT(u3)
FORMAT(u4)
FORMAT(ul)
FORMAT(voc)
FORMAT(vox)
// FORMAT(u1)
// FORMAT(u2)
// FORMAT(u3)
// FORMAT(u4)
// FORMAT(ul)
// FORMAT(voc)
// FORMAT(vox)
FORMAT(wav)
// FORMAT(wve)
// FORMAT(xa)

@ -1,167 +0,0 @@
/* This source code is a product of Sun Microsystems, Inc. and is provided
* for unrestricted use. Users may copy or modify this source code without
* charge.
*
* SUN SOURCE CODE IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING
* THE WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
* PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
*
* Sun source code is provided with no support and without any obligation on
* the part of Sun Microsystems, Inc. to assist in its use, correction,
* modification or enhancement.
*
* SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
* INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY THIS SOFTWARE
* OR ANY PART THEREOF.
*
* In no event will Sun Microsystems, Inc. be liable for any lost revenue
* or profits or other special, indirect and consequential damages, even if
* Sun has been advised of the possibility of such damages.
*
* Sun Microsystems, Inc.
* 2550 Garcia Avenue
* Mountain View, California 94043
*/
/*
* g721.c
*
* Description:
*
* g721_encoder(), g721_decoder()
*
* These routines comprise an implementation of the CCITT G.721 ADPCM
* coding algorithm. Essentially, this implementation is identical to
* the bit level description except for a few deviations which
* take advantage of work station attributes, such as hardware 2's
* complement arithmetic and large memory. Specifically, certain time
* consuming operations such as multiplications are replaced
* with lookup tables and software 2's complement operations are
* replaced with hardware 2's complement.
*
* The deviation from the bit level specification (lookup tables)
* preserves the bit level performance specifications.
*
* As outlined in the G.721 Recommendation, the algorithm is broken
* down into modules. Each section of code below is preceded by
* the name of the module which it is implementing.
*
*/
#include "sox_i.h"
#include "g72x.h"
#include "g711.h"
static const short qtab_721[7] = {-124, 80, 178, 246, 300, 349, 400};
/*
* Maps G.721 code word to reconstructed scale factor normalized log
* magnitude values.
*/
static const short _dqlntab[16] = {-2048, 4, 135, 213, 273, 323, 373, 425,
425, 373, 323, 273, 213, 135, 4, -2048};
/* Maps G.721 code word to log of scale factor multiplier. */
static const short _witab[16] = {-12, 18, 41, 64, 112, 198, 355, 1122,
1122, 355, 198, 112, 64, 41, 18, -12};
/*
* Maps G.721 code words to a set of values whose long and short
* term averages are computed and then compared to give an indication
* how stationary (steady state) the signal is.
*/
static const short _fitab[16] = {0, 0, 0, 0x200, 0x200, 0x200, 0x600, 0xE00,
0xE00, 0x600, 0x200, 0x200, 0x200, 0, 0, 0};
/*
* g721_encoder()
*
* Encodes the input vale of linear PCM, A-law or u-law data sl and returns
* the resulting code. -1 is returned for unknown input coding value.
*/
int g721_encoder(int sl, int in_coding, struct g72x_state *state_ptr)
{
short sezi, se, sez; /* ACCUM */
short d; /* SUBTA */
short sr; /* ADDB */
short y; /* MIX */
short dqsez; /* ADDC */
short dq, i;
switch (in_coding) { /* linearize input sample to 14-bit PCM */
case AUDIO_ENCODING_ALAW:
sl = sox_alaw2linear16(sl) >> 2;
break;
case AUDIO_ENCODING_ULAW:
sl = sox_ulaw2linear16(sl) >> 2;
break;
case AUDIO_ENCODING_LINEAR:
sl >>= 2; /* 14-bit dynamic range */
break;
default:
return (-1);
}
sezi = predictor_zero(state_ptr);
sez = sezi >> 1;
se = (sezi + predictor_pole(state_ptr)) >> 1; /* estimated signal */
d = sl - se; /* estimation difference */
/* quantize the prediction difference */
y = step_size(state_ptr); /* quantizer step size */
i = quantize(d, y, qtab_721, 7); /* i = ADPCM code */
dq = reconstruct(i & 8, _dqlntab[i], y); /* quantized est diff */
sr = (dq < 0) ? se - (dq & 0x3FFF) : se + dq; /* reconst. signal */
dqsez = sr + sez - se; /* pole prediction diff. */
update(4, y, _witab[i] << 5, _fitab[i], dq, sr, dqsez, state_ptr);
return (i);
}
/*
* g721_decoder()
*
* Description:
*
* Decodes a 4-bit code of G.721 encoded data of i and
* returns the resulting linear PCM, A-law or u-law value.
* return -1 for unknown out_coding value.
*/
int g721_decoder(int i, int out_coding, struct g72x_state *state_ptr)
{
short sezi, sei, sez, se; /* ACCUM */
short y; /* MIX */
short sr; /* ADDB */
short dq;
short dqsez;
i &= 0x0f; /* mask to get proper bits */
sezi = predictor_zero(state_ptr);
sez = sezi >> 1;
sei = sezi + predictor_pole(state_ptr);
se = sei >> 1; /* se = estimated signal */
y = step_size(state_ptr); /* dynamic quantizer step size */
dq = reconstruct(i & 0x08, _dqlntab[i], y); /* quantized diff. */
sr = (dq < 0) ? (se - (dq & 0x3FFF)) : se + dq; /* reconst. signal */
dqsez = sr - se + sez; /* pole prediction diff. */
update(4, y, _witab[i] << 5, _fitab[i], dq, sr, dqsez, state_ptr);
switch (out_coding) {
case AUDIO_ENCODING_ALAW:
return (tandem_adjust_alaw(sr, se, y, i, 8, qtab_721));
case AUDIO_ENCODING_ULAW:
return (tandem_adjust_ulaw(sr, se, y, i, 8, qtab_721));
case AUDIO_ENCODING_LINEAR:
return (sr << 2); /* sr was 14-bit dynamic range */
default:
return (-1);
}
}

@ -1,151 +0,0 @@
/* This source code is a product of Sun Microsystems, Inc. and is provided
* for unrestricted use. Users may copy or modify this source code without
* charge.
*
* SUN SOURCE CODE IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING
* THE WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
* PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
*
* Sun source code is provided with no support and without any obligation on
* the part of Sun Microsystems, Inc. to assist in its use, correction,
* modification or enhancement.
*
* SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
* INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY THIS SOFTWARE
* OR ANY PART THEREOF.
*
* In no event will Sun Microsystems, Inc. be liable for any lost revenue
* or profits or other special, indirect and consequential damages, even if
* Sun has been advised of the possibility of such damages.
*
* Sun Microsystems, Inc.
* 2550 Garcia Avenue
* Mountain View, California 94043
*/
/*
* g723_24.c
*
* Description:
*
* g723_24_encoder(), g723_24_decoder()
*
* These routines comprise an implementation of the CCITT G.723 24 Kbps
* ADPCM coding algorithm. Essentially, this implementation is identical to
* the bit level description except for a few deviations which take advantage
* of workstation attributes, such as hardware 2's complement arithmetic.
*
*/
#include "sox_i.h"
#include "g711.h"
#include "g72x.h"
/*
* Maps G.723_24 code word to reconstructed scale factor normalized log
* magnitude values.
*/
static const short _dqlntab[8] = {-2048, 135, 273, 373, 373, 273, 135, -2048};
/* Maps G.723_24 code word to log of scale factor multiplier. */
static const short _witab[8] = {-128, 960, 4384, 18624, 18624, 4384, 960, -128};
/*
* Maps G.723_24 code words to a set of values whose long and short
* term averages are computed and then compared to give an indication
* how stationary (steady state) the signal is.
*/
static const short _fitab[8] = {0, 0x200, 0x400, 0xE00, 0xE00, 0x400, 0x200, 0};
static const short qtab_723_24[3] = {8, 218, 331};
/*
* g723_24_encoder()
*
* Encodes a linear PCM, A-law or u-law input sample and returns its 3-bit code.
* Returns -1 if invalid input coding value.
*/
int g723_24_encoder(int sl, int in_coding, struct g72x_state *state_ptr)
{
short sei, sezi, se, sez; /* ACCUM */
short d; /* SUBTA */
short y; /* MIX */
short sr; /* ADDB */
short dqsez; /* ADDC */
short dq, i;
switch (in_coding) { /* linearize input sample to 14-bit PCM */
case AUDIO_ENCODING_ALAW:
sl = sox_alaw2linear16(sl) >> 2;
break;
case AUDIO_ENCODING_ULAW:
sl = sox_ulaw2linear16(sl) >> 2;
break;
case AUDIO_ENCODING_LINEAR:
sl >>= 2; /* sl of 14-bit dynamic range */
break;
default:
return (-1);
}
sezi = predictor_zero(state_ptr);
sez = sezi >> 1;
sei = sezi + predictor_pole(state_ptr);
se = sei >> 1; /* se = estimated signal */
d = sl - se; /* d = estimation diff. */
/* quantize prediction difference d */
y = step_size(state_ptr); /* quantizer step size */
i = quantize(d, y, qtab_723_24, 3); /* i = ADPCM code */
dq = reconstruct(i & 4, _dqlntab[i], y); /* quantized diff. */
sr = (dq < 0) ? se - (dq & 0x3FFF) : se + dq; /* reconstructed signal */
dqsez = sr + sez - se; /* pole prediction diff. */
update(3, y, _witab[i], _fitab[i], dq, sr, dqsez, state_ptr);
return (i);
}
/*
* g723_24_decoder()
*
* Decodes a 3-bit CCITT G.723_24 ADPCM code and returns
* the resulting 16-bit linear PCM, A-law or u-law sample value.
* -1 is returned if the output coding is unknown.
*/
int g723_24_decoder(int i, int out_coding, struct g72x_state *state_ptr)
{
short sezi, sei, sez, se; /* ACCUM */
short y; /* MIX */
short sr; /* ADDB */
short dq;
short dqsez;
i &= 0x07; /* mask to get proper bits */
sezi = predictor_zero(state_ptr);
sez = sezi >> 1;
sei = sezi + predictor_pole(state_ptr);
se = sei >> 1; /* se = estimated signal */
y = step_size(state_ptr); /* adaptive quantizer step size */
dq = reconstruct(i & 0x04, _dqlntab[i], y); /* unquantize pred diff */
sr = (dq < 0) ? (se - (dq & 0x3FFF)) : (se + dq); /* reconst. signal */
dqsez = sr - se + sez; /* pole prediction diff. */
update(3, y, _witab[i], _fitab[i], dq, sr, dqsez, state_ptr);
switch (out_coding) {
case AUDIO_ENCODING_ALAW:
return (tandem_adjust_alaw(sr, se, y, i, 4, qtab_723_24));
case AUDIO_ENCODING_ULAW:
return (tandem_adjust_ulaw(sr, se, y, i, 4, qtab_723_24));
case AUDIO_ENCODING_LINEAR:
return (sr << 2); /* sr was of 14-bit dynamic range */
default:
return (-1);
}
}

@ -1,171 +0,0 @@
/* This source code is a product of Sun Microsystems, Inc. and is provided
* for unrestricted use. Users may copy or modify this source code without
* charge.
*
* SUN SOURCE CODE IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING
* THE WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
* PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
*
* Sun source code is provided with no support and without any obligation on
* the part of Sun Microsystems, Inc. to assist in its use, correction,
* modification or enhancement.
*
* SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
* INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY THIS SOFTWARE
* OR ANY PART THEREOF.
*
* In no event will Sun Microsystems, Inc. be liable for any lost revenue
* or profits or other special, indirect and consequential damages, even if
* Sun has been advised of the possibility of such damages.
*
* Sun Microsystems, Inc.
* 2550 Garcia Avenue
* Mountain View, California 94043
*/
/*
* g723_40.c
*
* Description:
*
* g723_40_encoder(), g723_40_decoder()
*
* These routines comprise an implementation of the CCITT G.723 40Kbps
* ADPCM coding algorithm. Essentially, this implementation is identical to
* the bit level description except for a few deviations which
* take advantage of workstation attributes, such as hardware 2's
* complement arithmetic.
*
* The deviation from the bit level specification (lookup tables),
* preserves the bit level performance specifications.
*
* As outlined in the G.723 Recommendation, the algorithm is broken
* down into modules. Each section of code below is preceded by
* the name of the module which it is implementing.
*
*/
#include "sox_i.h"
#include "g711.h"
#include "g72x.h"
/*
* Maps G.723_40 code word to ructeconstructed scale factor normalized log
* magnitude values.
*/
static const short _dqlntab[32] = {-2048, -66, 28, 104, 169, 224, 274, 318,
358, 395, 429, 459, 488, 514, 539, 566,
566, 539, 514, 488, 459, 429, 395, 358,
318, 274, 224, 169, 104, 28, -66, -2048};
/* Maps G.723_40 code word to log of scale factor multiplier. */
static const short _witab[32] = {448, 448, 768, 1248, 1280, 1312, 1856, 3200,
4512, 5728, 7008, 8960, 11456, 14080, 16928, 22272,
22272, 16928, 14080, 11456, 8960, 7008, 5728, 4512,
3200, 1856, 1312, 1280, 1248, 768, 448, 448};
/*
* Maps G.723_40 code words to a set of values whose long and short
* term averages are computed and then compared to give an indication
* how stationary (steady state) the signal is.
*/
static const short _fitab[32] = {0, 0, 0, 0, 0, 0x200, 0x200, 0x200,
0x200, 0x200, 0x400, 0x600, 0x800, 0xA00, 0xC00, 0xC00,
0xC00, 0xC00, 0xA00, 0x800, 0x600, 0x400, 0x200, 0x200,
0x200, 0x200, 0x200, 0, 0, 0, 0, 0};
static const short qtab_723_40[15] = {-122, -16, 68, 139, 198, 250, 298, 339,
378, 413, 445, 475, 502, 528, 553};
/*
* g723_40_encoder()
*
* Encodes a 16-bit linear PCM, A-law or u-law input sample and retuens
* the resulting 5-bit CCITT G.723 40Kbps code.
* Returns -1 if the input coding value is invalid.
*/
int g723_40_encoder(int sl, int in_coding, struct g72x_state *state_ptr)
{
short sei, sezi, se, sez; /* ACCUM */
short d; /* SUBTA */
short y; /* MIX */
short sr; /* ADDB */
short dqsez; /* ADDC */
short dq, i;
switch (in_coding) { /* linearize input sample to 14-bit PCM */
case AUDIO_ENCODING_ALAW:
sl = sox_alaw2linear16(sl) >> 2;
break;
case AUDIO_ENCODING_ULAW:
sl = sox_ulaw2linear16(sl) >> 2;
break;
case AUDIO_ENCODING_LINEAR:
sl >>= 2; /* sl of 14-bit dynamic range */
break;
default:
return (-1);
}
sezi = predictor_zero(state_ptr);
sez = sezi >> 1;
sei = sezi + predictor_pole(state_ptr);
se = sei >> 1; /* se = estimated signal */
d = sl - se; /* d = estimation difference */
/* quantize prediction difference */
y = step_size(state_ptr); /* adaptive quantizer step size */
i = quantize(d, y, qtab_723_40, 15); /* i = ADPCM code */
dq = reconstruct(i & 0x10, _dqlntab[i], y); /* quantized diff */
sr = (dq < 0) ? se - (dq & 0x7FFF) : se + dq; /* reconstructed signal */
dqsez = sr + sez - se; /* dqsez = pole prediction diff. */
update(5, y, _witab[i], _fitab[i], dq, sr, dqsez, state_ptr);
return (i);
}
/*
* g723_40_decoder()
*
* Decodes a 5-bit CCITT G.723 40Kbps code and returns
* the resulting 16-bit linear PCM, A-law or u-law sample value.
* -1 is returned if the output coding is unknown.
*/
int g723_40_decoder(int i, int out_coding, struct g72x_state *state_ptr)
{
short sezi, sei, sez, se; /* ACCUM */
short y; /* MIX */
short sr; /* ADDB */
short dq;
short dqsez;
i &= 0x1f; /* mask to get proper bits */
sezi = predictor_zero(state_ptr);
sez = sezi >> 1;
sei = sezi + predictor_pole(state_ptr);
se = sei >> 1; /* se = estimated signal */
y = step_size(state_ptr); /* adaptive quantizer step size */
dq = reconstruct(i & 0x10, _dqlntab[i], y); /* estimation diff. */
sr = (dq < 0) ? (se - (dq & 0x7FFF)) : (se + dq); /* reconst. signal */
dqsez = sr - se + sez; /* pole prediction diff. */
update(5, y, _witab[i], _fitab[i], dq, sr, dqsez, state_ptr);
switch (out_coding) {
case AUDIO_ENCODING_ALAW:
return (tandem_adjust_alaw(sr, se, y, i, 0x10, qtab_723_40));
case AUDIO_ENCODING_ULAW:
return (tandem_adjust_ulaw(sr, se, y, i, 0x10, qtab_723_40));
case AUDIO_ENCODING_LINEAR:
return (sr << 2); /* sr was of 14-bit dynamic range */
default:
return (-1);
}
}

@ -1,575 +0,0 @@
/* Common routines for G.721 and G.723 conversions.
*
* (c) 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
*
*
* This code is based on code from Sun, which came with the following
* copyright notice:
* -----------------------------------------------------------------------
* This source code is a product of Sun Microsystems, Inc. and is provided
* for unrestricted use. Users may copy or modify this source code without
* charge.
*
* SUN SOURCE CODE IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING
* THE WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
* PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
*
* Sun source code is provided with no support and without any obligation on
* the part of Sun Microsystems, Inc. to assist in its use, correction,
* modification or enhancement.
*
* SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
* INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY THIS SOFTWARE
* OR ANY PART THEREOF.
*
* In no event will Sun Microsystems, Inc. be liable for any lost revenue
* or profits or other special, indirect and consequential damages, even if
* Sun has been advised of the possibility of such damages.
*
* Sun Microsystems, Inc.
* 2550 Garcia Avenue
* Mountain View, California 94043
* -----------------------------------------------------------------------
*/
#include "sox_i.h"
#include "g711.h"
#include "g72x.h"
static const char LogTable256[] =
{
0, 0, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3,
4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7
};
static inline int log2plus1(int val)
{
/* From http://graphics.stanford.edu/~seander/bithacks.html#IntegerLogLookup */
unsigned int v = (unsigned int)val; /* 32-bit word to find the log of */
unsigned r; /* r will be lg(v) */
register unsigned int t, tt; /* temporaries */
if ((tt = v >> 16))
{
r = (t = tt >> 8) ? 24 + LogTable256[t] : 16 + LogTable256[tt];
}
else
{
r = (t = v >> 8) ? 8 + LogTable256[t] : LogTable256[v];
}
return r + 1;
}
/*
* quan()
*
* quantizes the input val against the table of size short integers.
* It returns i if table[i - 1] <= val < table[i].
*
* Using linear search for simple coding.
*/
static int quan(int val, short const *table, int size)
{
int i;
for (i = 0; i < size; i++)
if (val < *table++)
break;
return (i);
}
/*
* fmult()
*
* returns the integer product of the 14-bit integer "an" and
* "floating point" representation (4-bit exponent, 6-bit mantessa) "srn".
*/
static int fmult(int an, int srn)
{
short anmag, anexp, anmant;
short wanexp, wanmant;
short retval;
anmag = (an > 0) ? an : ((-an) & 0x1FFF);
anexp = log2plus1(anmag) - 6;
anmant = (anmag == 0) ? 32 :
(anexp >= 0) ? anmag >> anexp : anmag << -anexp;
wanexp = anexp + ((srn >> 6) & 0xF) - 13;
wanmant = (anmant * (srn & 077) + 0x30) >> 4;
retval = (wanexp >= 0) ? ((wanmant << wanexp) & 0x7FFF) :
(wanmant >> -wanexp);
return (((an ^ srn) < 0) ? -retval : retval);
}
/*
* g72x_init_state()
*
* This routine initializes and/or resets the g72x_state structure
* pointed to by 'state_ptr'.
* All the initial state values are specified in the CCITT G.721 document.
*/
void g72x_init_state(struct g72x_state *state_ptr)
{
int cnta;
state_ptr->yl = 34816;
state_ptr->yu = 544;
state_ptr->dms = 0;
state_ptr->dml = 0;
state_ptr->ap = 0;
for (cnta = 0; cnta < 2; cnta++) {
state_ptr->a[cnta] = 0;
state_ptr->pk[cnta] = 0;
state_ptr->sr[cnta] = 32;
}
for (cnta = 0; cnta < 6; cnta++) {
state_ptr->b[cnta] = 0;
state_ptr->dq[cnta] = 32;
}
state_ptr->td = 0;
}
/*
* predictor_zero()
*
* computes the estimated signal from 6-zero predictor.
*
*/
int predictor_zero(struct g72x_state *state_ptr)
{
int i;
int sezi;
sezi = fmult(state_ptr->b[0] >> 2, state_ptr->dq[0]);
for (i = 1; i < 6; i++) /* ACCUM */
sezi += fmult(state_ptr->b[i] >> 2, state_ptr->dq[i]);
return (sezi);
}
/*
* predictor_pole()
*
* computes the estimated signal from 2-pole predictor.
*
*/
int predictor_pole(struct g72x_state *state_ptr)
{
return (fmult(state_ptr->a[1] >> 2, state_ptr->sr[1]) +
fmult(state_ptr->a[0] >> 2, state_ptr->sr[0]));
}
/*
* step_size()
*
* computes the quantization step size of the adaptive quantizer.
*
*/
int step_size(struct g72x_state *state_ptr)
{
int y;
int dif;
int al;
if (state_ptr->ap >= 256)
return (state_ptr->yu);
else {
y = state_ptr->yl >> 6;
dif = state_ptr->yu - y;
al = state_ptr->ap >> 2;
if (dif > 0)
y += (dif * al) >> 6;
else if (dif < 0)
y += (dif * al + 0x3F) >> 6;
return (y);
}
}
/*
* quantize()
*
* Given a raw sample, 'd', of the difference signal and a
* quantization step size scale factor, 'y', this routine returns the
* ADPCM codeword to which that sample gets quantized. The step
* size scale factor division operation is done in the log base 2 domain
* as a subtraction.
*/
int quantize(int d, int y, short const *table, int size)
{
short dqm; /* Magnitude of 'd' */
short exp; /* Integer part of base 2 log of 'd' */
short mant; /* Fractional part of base 2 log */
short dl; /* Log of magnitude of 'd' */
short dln; /* Step size scale factor normalized log */
int i;
/*
* LOG
*
* Compute base 2 log of 'd', and store in 'dl'.
*/
dqm = abs(d);
exp = log2plus1(dqm >> 1);
mant = ((dqm << 7) >> exp) & 0x7F; /* Fractional portion. */
dl = (exp << 7) + mant;
/*
* SUBTB
*
* "Divide" by step size multiplier.
*/
dln = dl - (y >> 2);
/*
* QUAN
*
* Obtain codword i for 'd'.
*/
i = quan(dln, table, size);
if (d < 0) /* take 1's complement of i */
return ((size << 1) + 1 - i);
else if (i == 0) /* take 1's complement of 0 */
return ((size << 1) + 1); /* new in 1988 */
else
return (i);
}
/*
* reconstruct()
*
* Returns reconstructed difference signal 'dq' obtained from
* codeword 'i' and quantization step size scale factor 'y'.
* Multiplication is performed in log base 2 domain as addition.
*/
int reconstruct(int sign, int dqln, int y)
{
short dql; /* Log of 'dq' magnitude */
short dex; /* Integer part of log */
short dqt;
short dq; /* Reconstructed difference signal sample */
dql = dqln + (y >> 2); /* ADDA */
if (dql < 0) {
return ((sign) ? -0x8000 : 0);
} else { /* ANTILOG */
dex = (dql >> 7) & 15;
dqt = 128 + (dql & 127);
dq = (dqt << 7) >> (14 - dex);
return ((sign) ? (dq - 0x8000) : dq);
}
}
/*
* update()
*
* updates the state variables for each output code
*/
void update(int code_size, int y, int wi, int fi, int dq, int sr,
int dqsez, struct g72x_state *state_ptr)
{
int cnt;
short mag, exp; /* Adaptive predictor, FLOAT A */
short a2p=0; /* LIMC */
short a1ul; /* UPA1 */
short pks1; /* UPA2 */
short fa1;
char tr; /* tone/transition detector */
short ylint, thr2, dqthr;
short ylfrac, thr1;
short pk0;
pk0 = (dqsez < 0) ? 1 : 0; /* needed in updating predictor poles */
mag = dq & 0x7FFF; /* prediction difference magnitude */
/* TRANS */
ylint = state_ptr->yl >> 15; /* exponent part of yl */
ylfrac = (state_ptr->yl >> 10) & 0x1F; /* fractional part of yl */
thr1 = (32 + ylfrac) << ylint; /* threshold */
thr2 = (ylint > 9) ? 31 << 10 : thr1; /* limit thr2 to 31 << 10 */
dqthr = (thr2 + (thr2 >> 1)) >> 1; /* dqthr = 0.75 * thr2 */
if (state_ptr->td == 0) /* signal supposed voice */
tr = 0;
else if (mag <= dqthr) /* supposed data, but small mag */
tr = 0; /* treated as voice */
else /* signal is data (modem) */
tr = 1;
/*
* Quantizer scale factor adaptation.
*/
/* FUNCTW & FILTD & DELAY */
/* update non-steady state step size multiplier */
state_ptr->yu = y + ((wi - y) >> 5);
/* LIMB */
if (state_ptr->yu < 544) /* 544 <= yu <= 5120 */
state_ptr->yu = 544;
else if (state_ptr->yu > 5120)
state_ptr->yu = 5120;
/* FILTE & DELAY */
/* update steady state step size multiplier */
state_ptr->yl += state_ptr->yu + ((-state_ptr->yl) >> 6);
/*
* Adaptive predictor coefficients.
*/
if (tr == 1) { /* reset a's and b's for modem signal */
state_ptr->a[0] = 0;
state_ptr->a[1] = 0;
state_ptr->b[0] = 0;
state_ptr->b[1] = 0;
state_ptr->b[2] = 0;
state_ptr->b[3] = 0;
state_ptr->b[4] = 0;
state_ptr->b[5] = 0;
} else { /* update a's and b's */
pks1 = pk0 ^ state_ptr->pk[0]; /* UPA2 */
/* update predictor pole a[1] */
a2p = state_ptr->a[1] - (state_ptr->a[1] >> 7);
if (dqsez != 0) {
fa1 = (pks1) ? state_ptr->a[0] : -state_ptr->a[0];
if (fa1 < -8191) /* a2p = function of fa1 */
a2p -= 0x100;
else if (fa1 > 8191)
a2p += 0xFF;
else
a2p += fa1 >> 5;
if (pk0 ^ state_ptr->pk[1])
{
/* LIMC */
if (a2p <= -12160)
a2p = -12288;
else if (a2p >= 12416)
a2p = 12288;
else
a2p -= 0x80;
}
else if (a2p <= -12416)
a2p = -12288;
else if (a2p >= 12160)
a2p = 12288;
else
a2p += 0x80;
}
/* Possible bug: a2p not initialized if dqsez == 0) */
/* TRIGB & DELAY */
state_ptr->a[1] = a2p;
/* UPA1 */
/* update predictor pole a[0] */
state_ptr->a[0] -= state_ptr->a[0] >> 8;
if (dqsez != 0)
{
if (pks1 == 0)
state_ptr->a[0] += 192;
else
state_ptr->a[0] -= 192;
}
/* LIMD */
a1ul = 15360 - a2p;
if (state_ptr->a[0] < -a1ul)
state_ptr->a[0] = -a1ul;
else if (state_ptr->a[0] > a1ul)
state_ptr->a[0] = a1ul;
/* UPB : update predictor zeros b[6] */
for (cnt = 0; cnt < 6; cnt++) {
if (code_size == 5) /* for 40Kbps G.723 */
state_ptr->b[cnt] -= state_ptr->b[cnt] >> 9;
else /* for G.721 and 24Kbps G.723 */
state_ptr->b[cnt] -= state_ptr->b[cnt] >> 8;
if (dq & 0x7FFF) { /* XOR */
if ((dq ^ state_ptr->dq[cnt]) >= 0)
state_ptr->b[cnt] += 128;
else
state_ptr->b[cnt] -= 128;
}
}
}
for (cnt = 5; cnt > 0; cnt--)
state_ptr->dq[cnt] = state_ptr->dq[cnt-1];
/* FLOAT A : convert dq[0] to 4-bit exp, 6-bit mantissa f.p. */
if (mag == 0) {
state_ptr->dq[0] = (dq >= 0) ? 0x20 : (short)(unsigned short)0xFC20;
} else {
exp = log2plus1(mag);
state_ptr->dq[0] = (dq >= 0) ?
(exp << 6) + ((mag << 6) >> exp) :
(exp << 6) + ((mag << 6) >> exp) - 0x400;
}
state_ptr->sr[1] = state_ptr->sr[0];
/* FLOAT B : convert sr to 4-bit exp., 6-bit mantissa f.p. */
if (sr == 0) {
state_ptr->sr[0] = 0x20;
} else if (sr > 0) {
exp = log2plus1(sr);
state_ptr->sr[0] = (exp << 6) + ((sr << 6) >> exp);
} else if (sr > -32768) {
mag = -sr;
exp = log2plus1(mag);
state_ptr->sr[0] = (exp << 6) + ((mag << 6) >> exp) - 0x400;
} else
state_ptr->sr[0] = (short)(unsigned short)0xFC20;
/* DELAY A */
state_ptr->pk[1] = state_ptr->pk[0];
state_ptr->pk[0] = pk0;
/* TONE */
if (tr == 1) /* this sample has been treated as data */
state_ptr->td = 0; /* next one will be treated as voice */
else if (a2p < -11776) /* small sample-to-sample correlation */
state_ptr->td = 1; /* signal may be data */
else /* signal is voice */
state_ptr->td = 0;
/*
* Adaptation speed control.
*/
state_ptr->dms += (fi - state_ptr->dms) >> 5; /* FILTA */
state_ptr->dml += (((fi << 2) - state_ptr->dml) >> 7); /* FILTB */
if (tr == 1)
state_ptr->ap = 256;
else if (y < 1536) /* SUBTC */
state_ptr->ap += (0x200 - state_ptr->ap) >> 4;
else if (state_ptr->td == 1)
state_ptr->ap += (0x200 - state_ptr->ap) >> 4;
else if (abs((state_ptr->dms << 2) - state_ptr->dml) >=
(state_ptr->dml >> 3))
state_ptr->ap += (0x200 - state_ptr->ap) >> 4;
else
state_ptr->ap += (-state_ptr->ap) >> 4;
}
/*
* tandem_adjust(sr, se, y, i, sign)
*
* At the end of ADPCM decoding, it simulates an encoder which may be receiving
* the output of this decoder as a tandem process. If the output of the
* simulated encoder differs from the input to this decoder, the decoder output
* is adjusted by one level of A-law or u-law codes.
*
* Input:
* sr decoder output linear PCM sample,
* se predictor estimate sample,
* y quantizer step size,
* i decoder input code,
* sign sign bit of code i
*
* Return:
* adjusted A-law or u-law compressed sample.
*/
int tandem_adjust_alaw(int sr, int se, int y, int i, int sign, short const *qtab)
{
unsigned char sp; /* A-law compressed 8-bit code */
short dx; /* prediction error */
char id; /* quantized prediction error */
int sd; /* adjusted A-law decoded sample value */
int im; /* biased magnitude of i */
int imx; /* biased magnitude of id */
if (sr <= -32768)
sr = -1;
sp = sox_13linear2alaw(((sr >> 1) << 3));/* short to A-law compression */
dx = (sox_alaw2linear16(sp) >> 2) - se; /* 16-bit prediction error */
id = quantize(dx, y, qtab, sign - 1);
if (id == i) { /* no adjustment on sp */
return (sp);
} else { /* sp adjustment needed */
/* ADPCM codes : 8, 9, ... F, 0, 1, ... , 6, 7 */
im = i ^ sign; /* 2's complement to biased unsigned */
imx = id ^ sign;
if (imx > im) { /* sp adjusted to next lower value */
if (sp & 0x80) {
sd = (sp == 0xD5) ? 0x55 :
((sp ^ 0x55) - 1) ^ 0x55;
} else {
sd = (sp == 0x2A) ? 0x2A :
((sp ^ 0x55) + 1) ^ 0x55;
}
} else { /* sp adjusted to next higher value */
if (sp & 0x80)
sd = (sp == 0xAA) ? 0xAA :
((sp ^ 0x55) + 1) ^ 0x55;
else
sd = (sp == 0x55) ? 0xD5 :
((sp ^ 0x55) - 1) ^ 0x55;
}
return (sd);
}
}
int tandem_adjust_ulaw(int sr, int se, int y, int i, int sign, short const *qtab)
{
unsigned char sp; /* u-law compressed 8-bit code */
short dx; /* prediction error */
char id; /* quantized prediction error */
int sd; /* adjusted u-law decoded sample value */
int im; /* biased magnitude of i */
int imx; /* biased magnitude of id */
if (sr <= -32768)
sr = 0;
sp = sox_14linear2ulaw((sr << 2));/* short to u-law compression */
dx = (sox_ulaw2linear16(sp) >> 2) - se; /* 16-bit prediction error */
id = quantize(dx, y, qtab, sign - 1);
if (id == i) {
return (sp);
} else {
/* ADPCM codes : 8, 9, ... F, 0, 1, ... , 6, 7 */
im = i ^ sign; /* 2's complement to biased unsigned */
imx = id ^ sign;
if (imx > im) { /* sp adjusted to next lower value */
if (sp & 0x80)
sd = (sp == 0xFF) ? 0x7E : sp + 1;
else
sd = (sp == 0) ? 0 : sp - 1;
} else { /* sp adjusted to next higher value */
if (sp & 0x80)
sd = (sp == 0x80) ? 0x80 : sp - 1;
else
sd = (sp == 0x7F) ? 0xFE : sp + 1;
}
return (sd);
}
}

@ -1,157 +0,0 @@
/* This source code is a product of Sun Microsystems, Inc. and is provided
* for unrestricted use. Users may copy or modify this source code without
* charge.
*
* SUN SOURCE CODE IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING
* THE WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
* PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
*
* Sun source code is provided with no support and without any obligation on
* the part of Sun Microsystems, Inc. to assist in its use, correction,
* modification or enhancement.
*
* SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
* INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY THIS SOFTWARE
* OR ANY PART THEREOF.
*
* In no event will Sun Microsystems, Inc. be liable for any lost revenue
* or profits or other special, indirect and consequential damages, even if
* Sun has been advised of the possibility of such damages.
*
* Sun Microsystems, Inc.
* 2550 Garcia Avenue
* Mountain View, California 94043
*/
/*
* g72x.h
*
* Header file for CCITT conversion routines.
*
*/
#ifndef _G72X_H
#define _G72X_H
/* aliases */
#define g721_decoder lsx_g721_decoder
#define g721_encoder lsx_g721_encoder
#define g723_24_decoder lsx_g723_24_decoder
#define g723_24_encoder lsx_g723_24_encoder
#define g723_40_decoder lsx_g723_40_decoder
#define g723_40_encoder lsx_g723_40_encoder
#define g72x_init_state lsx_g72x_init_state
#define predictor_pole lsx_g72x_predictor_pole
#define predictor_zero lsx_g72x_predictor_zero
#define quantize lsx_g72x_quantize
#define reconstruct lsx_g72x_reconstruct
#define step_size lsx_g72x_step_size
#define tandem_adjust_alaw lsx_g72x_tandem_adjust_alaw
#define tandem_adjust_ulaw lsx_g72x_tandem_adjust_ulaw
#define update lsx_g72x_update
#define AUDIO_ENCODING_ULAW (1) /* ISDN u-law */
#define AUDIO_ENCODING_ALAW (2) /* ISDN A-law */
#define AUDIO_ENCODING_LINEAR (3) /* PCM 2's-complement (0-center) */
/*
* The following is the definition of the state structure
* used by the G.721/G.723 encoder and decoder to preserve their internal
* state between successive calls. The meanings of the majority
* of the state structure fields are explained in detail in the
* CCITT Recommendation G.721. The field names are essentially indentical
* to variable names in the bit level description of the coding algorithm
* included in this Recommendation.
*/
struct g72x_state {
long yl; /* Locked or steady state step size multiplier. */
short yu; /* Unlocked or non-steady state step size multiplier. */
short dms; /* Short term energy estimate. */
short dml; /* Long term energy estimate. */
short ap; /* Linear weighting coefficient of 'yl' and 'yu'. */
short a[2]; /* Coefficients of pole portion of prediction filter. */
short b[6]; /* Coefficients of zero portion of prediction filter. */
short pk[2]; /*
* Signs of previous two samples of a partially
* reconstructed signal.
*/
short dq[6]; /*
* Previous 6 samples of the quantized difference
* signal represented in an internal floating point
* format.
*/
short sr[2]; /*
* Previous 2 samples of the quantized difference
* signal represented in an internal floating point
* format.
*/
char td; /* delayed tone detect, new in 1988 version */
};
/* External function definitions. */
extern void g72x_init_state(struct g72x_state *);
extern int g721_encoder(
int sample,
int in_coding,
struct g72x_state *state_ptr);
extern int g721_decoder(
int code,
int out_coding,
struct g72x_state *state_ptr);
extern int g723_16_encoder(
int sample,
int in_coding,
struct g72x_state *state_ptr);
extern int g723_16_decoder(
int code,
int out_coding,
struct g72x_state *state_ptr);
extern int g723_24_encoder(
int sample,
int in_coding,
struct g72x_state *state_ptr);
extern int g723_24_decoder(
int code,
int out_coding,
struct g72x_state *state_ptr);
extern int g723_40_encoder(
int sample,
int in_coding,
struct g72x_state *state_ptr);
extern int g723_40_decoder(
int code,
int out_coding,
struct g72x_state *state_ptr);
int predictor_zero(struct g72x_state *state_ptr);
int predictor_pole(struct g72x_state *state_ptr);
int step_size(struct g72x_state *state_ptr);
int quantize(int d,
int y,
short const *table,
int size);
int reconstruct(int sign,
int dqln,
int y);
void update(int code_size,
int y,
int wi,
int fi,
int dq,
int sr,
int dqsez,
struct g72x_state *state_ptr);
int tandem_adjust_alaw(int sr,
int se,
int y,
int i,
int sign,
short const *qtab);
int tandem_adjust_ulaw(int sr,
int se,
int y,
int i,
int sign,
short const *qtab);
#endif /* !_G72X_H */

@ -1,276 +0,0 @@
/* libSoX effect: gain/norm/etc. (c) 2008-9 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 <ctype.h>
#include <string.h>
typedef struct {
sox_bool do_equalise, do_balance, do_balance_no_clip, do_limiter;
sox_bool do_restore, make_headroom, do_normalise, do_scan;
double fixed_gain; /* Valid only in channel 0 */
double mult, reclaim, rms, limiter;
off_t num_samples;
sox_sample_t min, max;
FILE * tmp_file;
} priv_t;
static int create(sox_effect_t * effp, int argc, char * * argv)
{
priv_t * p = (priv_t *)effp->priv;
char const * q;
for (--argc, ++argv; argc && **argv == '-' && argv[0][1] &&
!isdigit((unsigned char)argv[0][1]) && argv[0][1] != '.'; --argc, ++argv)
for (q = &argv[0][1]; *q; ++q) switch (*q) {
case 'n': p->do_scan = p->do_normalise = sox_true; break;
case 'e': p->do_scan = p->do_equalise = sox_true; break;
case 'B': p->do_scan = p->do_balance = sox_true; break;
case 'b': p->do_scan = p->do_balance_no_clip = sox_true; break;
case 'r': p->do_scan = p->do_restore = sox_true; break;
case 'h': p->make_headroom = sox_true; break;
case 'l': p->do_limiter = sox_true; break;
default: lsx_fail("invalid option `-%c'", *q); return lsx_usage(effp);
}
if ((p->do_equalise + p->do_balance + p->do_balance_no_clip + p->do_restore)/ sox_true > 1) {
lsx_fail("only one of -e, -B, -b, -r may be given");
return SOX_EOF;
}
if (p->do_normalise && p->do_restore) {
lsx_fail("only one of -n, -r may be given");
return SOX_EOF;
}
if (p->do_limiter && p->make_headroom) {
lsx_fail("only one of -l, -h may be given");
return SOX_EOF;
}
do {NUMERIC_PARAMETER(fixed_gain, -HUGE_VAL, HUGE_VAL)} while (0);
p->fixed_gain = dB_to_linear(p->fixed_gain);
return argc? lsx_usage(effp) : SOX_SUCCESS;
}
static int start(sox_effect_t * effp)
{
priv_t * p = (priv_t *)effp->priv;
if (effp->flow == 0) {
if (p->do_restore) {
if (!effp->in_signal.mult || *effp->in_signal.mult >= 1) {
lsx_fail("can't reclaim headroom");
return SOX_EOF;
}
p->reclaim = 1 / *effp->in_signal.mult;
}
effp->out_signal.mult = p->make_headroom? &p->fixed_gain : NULL;
if (!p->do_equalise && !p->do_balance && !p->do_balance_no_clip)
effp->flows = 1; /* essentially a conditional SOX_EFF_MCHAN */
}
p->mult = 0;
p->max = 1;
p->min = -1;
if (p->do_scan) {
p->tmp_file = lsx_tmpfile();
if (p->tmp_file == NULL) {
lsx_fail("can't create temporary file: %s", strerror(errno));
return SOX_EOF;
}
}
if (p->do_limiter)
p->limiter = (1 - 1 / p->fixed_gain) * (1. / SOX_SAMPLE_MAX);
else if (p->fixed_gain == floor(p->fixed_gain) && !p->do_scan)
effp->out_signal.precision = effp->in_signal.precision;
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;
if (p->do_scan) {
if (fwrite(ibuf, sizeof(*ibuf), *isamp, p->tmp_file) != *isamp) {
lsx_fail("error writing temporary file: %s", strerror(errno));
return SOX_EOF;
}
if (p->do_balance && !p->do_normalise)
for (len = *isamp; len; --len, ++ibuf) {
double d = SOX_SAMPLE_TO_FLOAT_64BIT(*ibuf, effp->clips);
p->rms += sqr(d);
++p->num_samples;
}
else if (p->do_balance || p->do_balance_no_clip)
for (len = *isamp; len; --len, ++ibuf) {
double d = SOX_SAMPLE_TO_FLOAT_64BIT(*ibuf, effp->clips);
p->rms += sqr(d);
++p->num_samples;
p->max = max(p->max, *ibuf);
p->min = min(p->min, *ibuf);
}
else for (len = *isamp; len; --len, ++ibuf) {
p->max = max(p->max, *ibuf);
p->min = min(p->min, *ibuf);
}
*osamp = 0; /* samples not output until drain */
}
else {
double mult = ((priv_t *)(effp - effp->flow)->priv)->fixed_gain;
len = *isamp = *osamp = min(*isamp, *osamp);
if (!p->do_limiter) for (; len; --len, ++ibuf)
*obuf++ = SOX_ROUND_CLIP_COUNT(*ibuf * mult, effp->clips);
else for (; len; --len, ++ibuf) {
double d = *ibuf * mult;
*obuf++ = d < 0 ? 1 / (1 / d - p->limiter) - .5 :
d > 0 ? 1 / (1 / d + p->limiter) + .5 : 0;
}
}
return SOX_SUCCESS;
}
static void start_drain(sox_effect_t * effp)
{
priv_t * p = (priv_t *)effp->priv;
double max = SOX_SAMPLE_MAX, max_peak = 0, max_rms = 0;
size_t i;
if (p->do_balance || p->do_balance_no_clip) {
for (i = 0; i < effp->flows; ++i) {
priv_t * q = (priv_t *)(effp - effp->flow + i)->priv;
max_rms = max(max_rms, sqrt(q->rms / q->num_samples));
rewind(q->tmp_file);
}
for (i = 0; i < effp->flows; ++i) {
priv_t * q = (priv_t *)(effp - effp->flow + i)->priv;
double this_rms = sqrt(q->rms / q->num_samples);
double this_peak = max(q->max / max, q->min / (double)SOX_SAMPLE_MIN);
q->mult = this_rms != 0? max_rms / this_rms : 1;
max_peak = max(max_peak, q->mult * this_peak);
q->mult *= p->fixed_gain;
}
if (p->do_normalise || (p->do_balance_no_clip && max_peak > 1))
for (i = 0; i < effp->flows; ++i) {
priv_t * q = (priv_t *)(effp - effp->flow + i)->priv;
q->mult /= max_peak;
}
} else if (p->do_equalise && !p->do_normalise) {
for (i = 0; i < effp->flows; ++i) {
priv_t * q = (priv_t *)(effp - effp->flow + i)->priv;
double this_peak = max(q->max / max, q->min / (double)SOX_SAMPLE_MIN);
max_peak = max(max_peak, this_peak);
q->mult = p->fixed_gain / this_peak;
rewind(q->tmp_file);
}
for (i = 0; i < effp->flows; ++i) {
priv_t * q = (priv_t *)(effp - effp->flow + i)->priv;
q->mult *= max_peak;
}
} else {
p->mult = min(max / p->max, (double)SOX_SAMPLE_MIN / p->min);
if (p->do_restore) {
if (p->reclaim > p->mult)
lsx_report("%.3gdB not reclaimed", linear_to_dB(p->reclaim / p->mult));
else p->mult = p->reclaim;
}
p->mult *= p->fixed_gain;
rewind(p->tmp_file);
}
}
static int drain(sox_effect_t * effp, sox_sample_t * obuf, size_t * osamp)
{
priv_t * p = (priv_t *)effp->priv;
size_t len;
int result = SOX_SUCCESS;
*osamp -= *osamp % effp->in_signal.channels;
if (p->do_scan) {
if (!p->mult)
start_drain(effp);
len = fread(obuf, sizeof(*obuf), *osamp, p->tmp_file);
if (len != *osamp && !feof(p->tmp_file)) {
lsx_fail("error reading temporary file: %s", strerror(errno));
result = SOX_EOF;
}
if (!p->do_limiter) for (*osamp = len; len; --len, ++obuf)
*obuf = SOX_ROUND_CLIP_COUNT(*obuf * p->mult, effp->clips);
else for (*osamp = len; len; --len) {
double d = *obuf * p->mult;
*obuf++ = d < 0 ? 1 / (1 / d - p->limiter) - .5 :
d > 0 ? 1 / (1 / d + p->limiter) + .5 : 0;
}
}
else *osamp = 0;
return result;
}
static int stop(sox_effect_t * effp)
{
priv_t * p = (priv_t *)effp->priv;
if (p->do_scan)
fclose(p->tmp_file); /* auto-deleted by lsx_tmpfile */
return SOX_SUCCESS;
}
sox_effect_handler_t const * lsx_gain_effect_fn(void)
{
static sox_effect_handler_t handler = {
"gain", NULL, SOX_EFF_GAIN,
create, start, flow, drain, stop, NULL, sizeof(priv_t)};
static char const * lines[] = {
"[-e|-b|-B|-r] [-n] [-l|-h] [gain-dB]",
"-e\t Equalise channels: peak to that with max peak;",
"-B\t Balance channels: rms to that with max rms; no clip protection",
"-b\t Balance channels: rms to that with max rms; clip protection",
"\t Note -Bn = -bn",
"-r\t Reclaim headroom (as much as possible without clipping); see -h",
"-n\t Norm file to 0dBfs(output precision); gain-dB, if present, usually <0",
"-l\t Use simple limiter",
"-h\t Apply attenuation for headroom for subsequent effects; gain-dB, if",
"\t present, is subject to reclaim by a subsequent gain -r",
"gain-dB\t Apply gain in dB",
};
static char * usage;
handler.usage = lsx_usage_lines(&usage, lines, array_length(lines));
return &handler;
}
/*------------------ emulation of the old `normalise' effect -----------------*/
static int norm_getopts(sox_effect_t * effp, int argc, char * * argv)
{
char * argv2[3];
int argc2 = 2;
argv2[0] = argv[0], --argc, ++argv;
argv2[1] = "-n";
if (argc)
argv2[argc2++] = *argv, --argc, ++argv;
return argc? lsx_usage(effp) :
lsx_gain_effect_fn()->getopts(effp, argc2, argv2);
}
sox_effect_handler_t const * lsx_norm_effect_fn(void)
{
static sox_effect_handler_t handler;
handler = *lsx_gain_effect_fn();
handler.name = "norm";
handler.usage = "[level]";
handler.getopts = norm_getopts;
return &handler;
}

@ -1,102 +0,0 @@
/* libSoX effect: Hilbert transform filter
*
* First version of this effect written 11/2011 by Ulrich Klauer, using maths
* from "Understanding digital signal processing" by Richard G. Lyons.
*
* 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"
#include "dft_filter.h"
typedef struct {
dft_filter_priv_t base;
double *h;
int taps;
} priv_t;
static int getopts(sox_effect_t *effp, int argc, char **argv)
{
lsx_getopt_t optstate;
int c;
priv_t *p = (priv_t*)effp->priv;
dft_filter_priv_t *b = &p->base;
b->filter_ptr = &b->filter;
lsx_getopt_init(argc, argv, "+n:", NULL, lsx_getopt_flag_none, 1, &optstate);
while ((c = lsx_getopt(&optstate)) != -1) switch (c) {
GETOPT_NUMERIC(optstate, 'n', taps, 3, 32767)
default: lsx_fail("invalid option `-%c'", optstate.opt); return lsx_usage(effp);
}
if (p->taps && p->taps%2 == 0) {
lsx_fail("only filters with an odd number of taps are supported");
return SOX_EOF;
}
return optstate.ind != argc ? lsx_usage(effp) : SOX_SUCCESS;
}
static int start(sox_effect_t *effp)
{
priv_t *p = (priv_t*)effp->priv;
dft_filter_t *f = p->base.filter_ptr;
if (!f->num_taps) {
int i;
if (!p->taps) {
p->taps = effp->in_signal.rate/76.5 + 2;
p->taps += 1 - (p->taps%2);
/* results in a cutoff frequency of about 75 Hz with a Blackman window */
lsx_debug("choosing number of taps = %d (override with -n)", p->taps);
}
lsx_valloc(p->h, p->taps);
for (i = 0; i < p->taps; i++) {
int k = -(p->taps/2) + i;
if (k%2 == 0) {
p->h[i] = 0.0;
} else {
double pk = M_PI * k;
p->h[i] = (1 - cos(pk))/pk;
}
}
lsx_apply_blackman(p->h, p->taps, .16);
if (effp->global_info->plot != sox_plot_off) {
char title[100];
sprintf(title, "SoX effect: hilbert (%d taps)", p->taps);
lsx_plot_fir(p->h, p->taps, effp->in_signal.rate,
effp->global_info->plot, title, -20., 5.);
free(p->h);
return SOX_EOF;
}
lsx_set_dft_filter(f, p->h, p->taps, p->taps/2);
}
return lsx_dft_filter_effect_fn()->start(effp);
}
sox_effect_handler_t const *lsx_hilbert_effect_fn(void)
{
static sox_effect_handler_t handler;
handler = *lsx_dft_filter_effect_fn();
handler.name = "hilbert";
handler.usage = "[-n taps]";
handler.getopts = getopts;
handler.start = start;
handler.priv_size = sizeof(priv_t);
return &handler;
}

@ -1,227 +0,0 @@
/* libSoX MP3 utilities Copyright (c) 2007-9 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 "id3.h"
#ifdef HAVE_ID3TAG
#include <id3tag.h>
static char const * id3tagmap[][2] =
{
{"TIT2", "Title"},
{"TPE1", "Artist"},
{"TALB", "Album"},
{"TCOM", "Composer"},
{"TRCK", "Tracknumber"},
{"TDRC", "Year"},
{"TCON", "Genre"},
{"COMM", "Comment"},
{"TPOS", "Discnumber"},
{NULL, NULL}
};
static id3_utf8_t * utf8_id3tag_findframe(
struct id3_tag * tag, const char * const frameid, unsigned index)
{
struct id3_frame const * frame = id3_tag_findframe(tag, frameid, index);
if (frame) {
unsigned nfields = frame->nfields;
while (nfields--) {
union id3_field const *field = id3_frame_field(frame, nfields);
int ftype = id3_field_type(field);
const id3_ucs4_t *ucs4 = NULL;
unsigned nstrings;
switch (ftype) {
case ID3_FIELD_TYPE_STRING:
ucs4 = id3_field_getstring(field);
break;
case ID3_FIELD_TYPE_STRINGFULL:
ucs4 = id3_field_getfullstring(field);
break;
case ID3_FIELD_TYPE_STRINGLIST:
nstrings = id3_field_getnstrings(field);
while (nstrings--) {
ucs4 = id3_field_getstrings(field, nstrings);
if (ucs4)
break;
}
break;
}
if (ucs4)
return id3_ucs4_utf8duplicate(ucs4); /* Must call free() on this */
}
}
return NULL;
}
struct tag_info_node
{
struct tag_info_node * next;
off_t start;
off_t end;
};
struct tag_info {
sox_format_t * ft;
struct tag_info_node * head;
struct id3_tag * tag;
};
static int add_tag(struct tag_info * info)
{
struct tag_info_node * current;
off_t start, end;
id3_byte_t query[ID3_TAG_QUERYSIZE];
id3_byte_t * buffer;
long size;
int result = 0;
/* Ensure we're at the start of a valid tag and get its size. */
if (ID3_TAG_QUERYSIZE != lsx_readbuf(info->ft, query, ID3_TAG_QUERYSIZE) ||
!(size = id3_tag_query(query, ID3_TAG_QUERYSIZE))) {
return 0;
}
if (size < 0) {
if (0 != lsx_seeki(info->ft, size, SEEK_CUR) ||
ID3_TAG_QUERYSIZE != lsx_readbuf(info->ft, query, ID3_TAG_QUERYSIZE) ||
(size = id3_tag_query(query, ID3_TAG_QUERYSIZE)) <= 0) {
return 0;
}
}
/* Don't read a tag more than once. */
start = lsx_tell(info->ft);
end = start + size;
for (current = info->head; current; current = current->next) {
if (start == current->start && end == current->end) {
return 1;
} else if (start < current->end && current->start < end) {
return 0;
}
}
buffer = lsx_malloc((size_t)size);
if (!buffer) {
return 0;
}
memcpy(buffer, query, ID3_TAG_QUERYSIZE);
if ((unsigned long)size - ID3_TAG_QUERYSIZE ==
lsx_readbuf(info->ft, buffer + ID3_TAG_QUERYSIZE, (size_t)size - ID3_TAG_QUERYSIZE)) {
struct id3_tag * tag = id3_tag_parse(buffer, (size_t)size);
if (tag) {
current = lsx_malloc(sizeof(struct tag_info_node));
if (current) {
current->next = info->head;
current->start = start;
current->end = end;
info->head = current;
if (info->tag && (info->tag->extendedflags & ID3_TAG_EXTENDEDFLAG_TAGISANUPDATE)) {
struct id3_frame * frame;
unsigned i;
for (i = 0; (frame = id3_tag_findframe(tag, NULL, i)); i++) {
id3_tag_attachframe(info->tag, frame);
}
id3_tag_delete(tag);
} else {
if (info->tag) {
id3_tag_delete(info->tag);
}
info->tag = tag;
}
}
}
}
free(buffer);
return result;
}
void lsx_id3_read_tag(sox_format_t * ft, sox_bool search)
{
struct tag_info info;
id3_utf8_t * utf8;
int i;
int has_id3v1 = 0;
info.ft = ft;
info.head = NULL;
info.tag = NULL;
/*
We look for:
ID3v1 at end (EOF - 128).
ID3v2 at start.
ID3v2 at end (but before ID3v1 from end if there was one).
*/
if (search) {
if (0 == lsx_seeki(ft, -128, SEEK_END)) {
has_id3v1 =
add_tag(&info) &&
1 == ID3_TAG_VERSION_MAJOR(id3_tag_version(info.tag));
}
if (0 == lsx_seeki(ft, 0, SEEK_SET)) {
add_tag(&info);
}
if (0 == lsx_seeki(ft, has_id3v1 ? -138 : -10, SEEK_END)) {
add_tag(&info);
}
} else {
add_tag(&info);
}
if (info.tag && info.tag->frames) {
for (i = 0; id3tagmap[i][0]; ++i) {
if ((utf8 = utf8_id3tag_findframe(info.tag, id3tagmap[i][0], 0))) {
char * comment = lsx_malloc(strlen(id3tagmap[i][1]) + 1 + strlen((char *)utf8) + 1);
sprintf(comment, "%s=%s", id3tagmap[i][1], utf8);
sox_append_comment(&ft->oob.comments, comment);
free(comment);
free(utf8);
}
}
if ((utf8 = utf8_id3tag_findframe(info.tag, "TLEN", 0))) {
unsigned long tlen = strtoul((char *)utf8, NULL, 10);
if (tlen > 0 && tlen < ULONG_MAX) {
ft->signal.length= tlen; /* In ms; convert to samples later */
lsx_debug("got exact duration from ID3 TLEN");
}
free(utf8);
}
}
while (info.head) {
struct tag_info_node * head = info.head;
info.head = head->next;
free(head);
}
if (info.tag) {
id3_tag_delete(info.tag);
}
}
#else
/* Stub for format modules */
void lsx_id3_read_tag(sox_format_t *ft, sox_bool search) { }
#endif

@ -1,25 +0,0 @@
/* libSoX MP3 utilities Copyright (c) 2007-9 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
*/
#ifndef SOX_ID3_H
#define SOX_ID3_H
#include "sox_i.h"
void lsx_id3_read_tag(sox_format_t *ft, sox_bool search);
#endif

@ -1,33 +0,0 @@
/* libSoX format: raw IMA ADPCM (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
*/
#include "sox_i.h"
#include "adpcms.h"
#include "vox.h"
LSX_FORMAT_HANDLER(ima)
{
static char const * const names[] = {"ima", NULL};
static unsigned const write_encodings[] = {SOX_ENCODING_IMA_ADPCM, 4, 0, 0};
static sox_format_handler_t handler = {SOX_LIB_VERSION_CODE,
"Raw IMA ADPCM", names, SOX_FILE_MONO,
lsx_ima_start, lsx_vox_read, lsx_vox_stopread,
lsx_ima_start, lsx_vox_write, lsx_vox_stopwrite,
lsx_rawseek, write_encodings, NULL, sizeof(adpcm_io_t)
};
return &handler;
}

@ -1,21 +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
*/
#include "sox_i.h"
#include "raw.h"
RAW_FORMAT(la, 8, SOX_FILE_BIT_REV, ALAW)

@ -1,492 +0,0 @@
/* LADSPA effect support for sox
* (c) Reuben Thomas <rrt@sc3d.org> 2007
*
* 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_LADSPA_H
#include <assert.h>
#include <limits.h>
#include <string.h>
#include <math.h>
#include "ladspa.h"
/*
* Assuming LADSPA_Data == float. This is the case in 2012 and has been
* the case for many years now.
*/
#define SOX_SAMPLE_TO_LADSPA_DATA(d,clips) \
SOX_SAMPLE_TO_FLOAT_32BIT((d),(clips))
#define LADSPA_DATA_TO_SOX_SAMPLE(d,clips) \
SOX_FLOAT_32BIT_TO_SAMPLE((d),(clips))
static sox_effect_handler_t sox_ladspa_effect;
/* Private data for resampling */
typedef struct {
char *name; /* plugin name */
lt_dlhandle lth; /* dynamic object handle */
sox_bool clone;
const LADSPA_Descriptor *desc; /* plugin descriptor */
LADSPA_Handle *handles; /* instantiated plugin handles */
size_t handle_count;
LADSPA_Data *control; /* control ports */
unsigned long *inputs;
size_t input_count;
unsigned long *outputs;
size_t output_count;
sox_bool latency_compensation;
LADSPA_Data *latency_control_port;
unsigned long in_latency;
unsigned long out_latency;
} priv_t;
static LADSPA_Data ladspa_default(const LADSPA_PortRangeHint *p)
{
LADSPA_Data d;
if (LADSPA_IS_HINT_DEFAULT_0(p->HintDescriptor))
d = 0.0;
else if (LADSPA_IS_HINT_DEFAULT_1(p->HintDescriptor))
d = 1.0;
else if (LADSPA_IS_HINT_DEFAULT_100(p->HintDescriptor))
d = 100.0;
else if (LADSPA_IS_HINT_DEFAULT_440(p->HintDescriptor))
d = 440.0;
else if (LADSPA_IS_HINT_DEFAULT_MINIMUM(p->HintDescriptor))
d = p->LowerBound;
else if (LADSPA_IS_HINT_DEFAULT_MAXIMUM(p->HintDescriptor))
d = p->UpperBound;
else if (LADSPA_IS_HINT_DEFAULT_LOW(p->HintDescriptor)) {
if (LADSPA_IS_HINT_LOGARITHMIC(p->HintDescriptor))
d = exp(log(p->LowerBound) * 0.75 + log(p->UpperBound) * 0.25);
else
d = p->LowerBound * 0.75 + p->UpperBound * 0.25;
} else if (LADSPA_IS_HINT_DEFAULT_MIDDLE(p->HintDescriptor)) {
if (LADSPA_IS_HINT_LOGARITHMIC(p->HintDescriptor))
d = exp(log(p->LowerBound) * 0.5 + log(p->UpperBound) * 0.5);
else
d = p->LowerBound * 0.5 + p->UpperBound * 0.5;
} else if (LADSPA_IS_HINT_DEFAULT_HIGH(p->HintDescriptor)) {
if (LADSPA_IS_HINT_LOGARITHMIC(p->HintDescriptor))
d = exp(log(p->LowerBound) * 0.25 + log(p->UpperBound) * 0.75);
else
d = p->LowerBound * 0.25 + p->UpperBound * 0.75;
} else { /* shouldn't happen */
/* FIXME: Deal with this at a higher level */
lsx_fail("non-existent default value; using 0.1");
d = 0.1; /* Should at least avoid divide by 0 */
}
return d;
}
/*
* Process options
*/
static int sox_ladspa_getopts(sox_effect_t *effp, int argc, char **argv)
{
priv_t * l_st = (priv_t *)effp->priv;
char *path;
int c;
union {LADSPA_Descriptor_Function fn; lt_ptr ptr;} ltptr;
unsigned long index = 0, i;
double arg;
lsx_getopt_t optstate;
lsx_getopt_init(argc, argv, "+rl", NULL, lsx_getopt_flag_none, 1, &optstate);
while ((c = lsx_getopt(&optstate)) != -1) switch (c) {
case 'r': l_st->clone = sox_true; break;
case 'l': l_st->latency_compensation = sox_true; break;
default:
lsx_fail("unknown option `-%c'", optstate.opt);
return lsx_usage(effp);
}
argc -= optstate.ind, argv += optstate.ind;
/* Get module name */
if (argc >= 1) {
l_st->name = argv[0];
argc--; argv++;
}
/* Load module */
path = getenv("LADSPA_PATH");
if (path == NULL)
path = LADSPA_PATH;
if(lt_dlinit() || lt_dlsetsearchpath(path)
|| (l_st->lth = lt_dlopenext(l_st->name)) == NULL) {
lsx_fail("could not open LADSPA plugin %s", l_st->name);
return SOX_EOF;
}
/* Get descriptor function */
if ((ltptr.ptr = lt_dlsym(l_st->lth, "ladspa_descriptor")) == NULL) {
lsx_fail("could not find ladspa_descriptor");
return SOX_EOF;
}
/* If no plugins in this module, complain */
if (ltptr.fn(0UL) == NULL) {
lsx_fail("no plugins found");
return SOX_EOF;
}
/* Get first plugin descriptor */
l_st->desc = ltptr.fn(0UL);
assert(l_st->desc); /* We already know this will work */
/* If more than one plugin, or first argument is not a number, try
to use first argument as plugin label. */
if (argc > 0 && (ltptr.fn(1UL) != NULL || !sscanf(argv[0], "%lf", &arg))) {
while (l_st->desc && strcmp(l_st->desc->Label, argv[0]) != 0)
l_st->desc = ltptr.fn(++index);
if (l_st->desc == NULL) {
lsx_fail("no plugin called `%s' found", argv[0]);
return SOX_EOF;
}
argc--; argv++;
}
/* Scan the ports for inputs and outputs */
l_st->control = lsx_calloc(l_st->desc->PortCount, sizeof(LADSPA_Data));
l_st->inputs = lsx_malloc(l_st->desc->PortCount * sizeof(unsigned long));
l_st->outputs = lsx_malloc(l_st->desc->PortCount * sizeof(unsigned long));
for (i = 0; i < l_st->desc->PortCount; i++) {
const LADSPA_PortDescriptor port = l_st->desc->PortDescriptors[i];
/* Check port is well specified. All control ports should be
inputs, but don't bother checking, as we never rely on this. */
if (LADSPA_IS_PORT_INPUT(port) && LADSPA_IS_PORT_OUTPUT(port)) {
lsx_fail("port %lu is both input and output", i);
return SOX_EOF;
} else if (LADSPA_IS_PORT_CONTROL(port) && LADSPA_IS_PORT_AUDIO(port)) {
lsx_fail("port %lu is both audio and control", i);
return SOX_EOF;
}
if (LADSPA_IS_PORT_AUDIO(port)) {
if (LADSPA_IS_PORT_INPUT(port)) {
l_st->inputs[l_st->input_count++] = i;
} else if (LADSPA_IS_PORT_OUTPUT(port)) {
l_st->outputs[l_st->output_count++] = i;
}
} else { /* Control port */
if (l_st->latency_compensation &&
LADSPA_IS_PORT_CONTROL(port) &&
LADSPA_IS_PORT_OUTPUT(port) &&
strcmp(l_st->desc->PortNames[i], "latency") == 0) {
/* automatic latency compensation, Ardour does this, too */
l_st->latency_control_port = &l_st->control[i];
assert(*l_st->latency_control_port == 0);
lsx_debug("latency control port is %lu", i);
} else if (argc == 0) {
if (!LADSPA_IS_HINT_HAS_DEFAULT(l_st->desc->PortRangeHints[i].HintDescriptor)) {
lsx_fail("not enough arguments for control ports");
return SOX_EOF;
}
l_st->control[i] = ladspa_default(&(l_st->desc->PortRangeHints[i]));
lsx_debug("default argument for port %lu is %f", i, l_st->control[i]);
} else {
if (!sscanf(argv[0], "%lf", &arg))
return lsx_usage(effp);
l_st->control[i] = (LADSPA_Data)arg;
lsx_debug("argument for port %lu is %f", i, l_st->control[i]);
argc--; argv++;
}
}
}
/* Stop if we have any unused arguments */
return argc? lsx_usage(effp) : SOX_SUCCESS;
}
/*
* Prepare processing.
*/
static int sox_ladspa_start(sox_effect_t * effp)
{
priv_t * l_st = (priv_t *)effp->priv;
unsigned long i;
size_t h;
unsigned long rate = (unsigned long)effp->in_signal.rate;
/* Instantiate the plugin */
lsx_debug("rate for plugin is %g", effp->in_signal.rate);
if (l_st->input_count == 1 && l_st->output_count == 1 &&
effp->in_signal.channels == effp->out_signal.channels) {
/* for mono plugins, they are common */
if (!l_st->clone && effp->in_signal.channels > 1) {
lsx_fail("expected 1 input channel(s), found %u; consider using -r",
effp->in_signal.channels);
return SOX_EOF;
}
/*
* create one handle per channel for mono plugins. ecasound does this, too.
* mono LADSPA plugins are common and SoX supported mono LADSPA plugins
* exclusively for a while.
*/
l_st->handles = lsx_malloc(effp->in_signal.channels *
sizeof(LADSPA_Handle *));
while (l_st->handle_count < effp->in_signal.channels)
l_st->handles[l_st->handle_count++] = l_st->desc->instantiate(l_st->desc, rate);
} else {
/*
* assume the plugin is multi-channel capable with one instance,
* Some LADSPA plugins are stereo (e.g. bs2b-ladspa)
*/
if (l_st->input_count < effp->in_signal.channels) {
lsx_fail("fewer plugin input ports than input channels (%u < %u)",
(unsigned)l_st->input_count, effp->in_signal.channels);
return SOX_EOF;
}
/* warn if LADSPA audio ports are unused. ecasound does this, too */
if (l_st->input_count > effp->in_signal.channels)
lsx_warn("more plugin input ports than input channels (%u > %u)",
(unsigned)l_st->input_count, effp->in_signal.channels);
/*
* some LADSPA plugins increase/decrease the channel count
* (e.g. "mixer" in cmt or vocoder):
*/
if (l_st->output_count != effp->out_signal.channels) {
lsx_debug("changing output channels to match plugin output ports (%u => %u)",
effp->out_signal.channels, (unsigned)l_st->output_count);
effp->out_signal.channels = l_st->output_count;
}
l_st->handle_count = 1;
l_st->handles = lsx_malloc(sizeof(LADSPA_Handle *));
l_st->handles[0] = l_st->desc->instantiate(l_st->desc, rate);
}
/* abandon everything completely on any failed handle instantiation */
for (h = 0; h < l_st->handle_count; h++) {
if (l_st->handles[h] == NULL) {
/* cleanup the handles that did instantiate successfully */
for (h = 0; l_st->desc->cleanup && h < l_st->handle_count; h++) {
if (l_st->handles[h])
l_st->desc->cleanup(l_st->handles[h]);
}
free(l_st->handles);
l_st->handle_count = 0;
lsx_fail("could not instantiate plugin");
return SOX_EOF;
}
}
for (i = 0; i < l_st->desc->PortCount; i++) {
const LADSPA_PortDescriptor port = l_st->desc->PortDescriptors[i];
if (LADSPA_IS_PORT_CONTROL(port)) {
for (h = 0; h < l_st->handle_count; h++)
l_st->desc->connect_port(l_st->handles[h], i, &(l_st->control[i]));
}
}
/* If needed, activate the plugin instances */
if (l_st->desc->activate) {
for (h = 0; h < l_st->handle_count; h++)
l_st->desc->activate(l_st->handles[h]);
}
return SOX_SUCCESS;
}
/*
* Process one bufferful of data.
*/
static int sox_ladspa_flow(sox_effect_t * effp, const sox_sample_t *ibuf, sox_sample_t *obuf,
size_t *isamp, size_t *osamp)
{
priv_t * l_st = (priv_t *)effp->priv;
size_t i, len = min(*isamp, *osamp);
size_t j;
size_t h;
const size_t total_input_count = l_st->input_count * l_st->handle_count;
const size_t total_output_count = l_st->output_count * l_st->handle_count;
const size_t input_len = len / total_input_count;
size_t output_len = len / total_output_count;
if (total_output_count < total_input_count)
output_len = input_len;
*isamp = len;
*osamp = 0;
if (len) {
LADSPA_Data *buf = lsx_calloc(len, sizeof(LADSPA_Data));
LADSPA_Data *outbuf = lsx_calloc(len, sizeof(LADSPA_Data));
LADSPA_Handle handle;
unsigned long port, l;
SOX_SAMPLE_LOCALS;
/*
* prepare buffer for LADSPA input
* deinterleave sox samples and write non-interleaved data to
* input_port-specific buffer locations
*/
for (i = 0; i < input_len; i++) {
for (j = 0; j < total_input_count; j++) {
const sox_sample_t s = *ibuf++;
buf[j * input_len + i] = SOX_SAMPLE_TO_LADSPA_DATA(s, effp->clips);
}
}
/* Connect the LADSPA input port(s) to the prepared buffers */
for (j = 0; j < total_input_count; j++) {
handle = l_st->handles[j / l_st->input_count];
port = l_st->inputs[j / l_st->handle_count];
l_st->desc->connect_port(handle, port, buf + j * input_len);
}
/* Connect the LADSPA output port(s) if used */
for (j = 0; j < total_output_count; j++) {
handle = l_st->handles[j / l_st->output_count];
port = l_st->outputs[j / l_st->handle_count];
l_st->desc->connect_port(handle, port, outbuf + j * output_len);
}
/* Run the plugin for each handle */
for (h = 0; h < l_st->handle_count; h++)
l_st->desc->run(l_st->handles[h], input_len);
/* check the latency control port if we have one */
if (l_st->latency_control_port) {
lsx_debug("latency detected is %g", *l_st->latency_control_port);
l_st->in_latency = (unsigned long)floor(*l_st->latency_control_port);
/* we will need this later in sox_ladspa_drain */
l_st->out_latency = l_st->in_latency;
/* latency for plugins is constant, only compensate once */
l_st->latency_control_port = NULL;
}
/* Grab output if effect produces it, re-interleaving it */
l = min(output_len, l_st->in_latency);
for (i = l; i < output_len; i++) {
for (j = 0; j < total_output_count; j++) {
LADSPA_Data d = outbuf[j * output_len + i];
*obuf++ = LADSPA_DATA_TO_SOX_SAMPLE(d, effp->clips);
(*osamp)++;
}
}
l_st->in_latency -= l;
free(outbuf);
free(buf);
}
return SOX_SUCCESS;
}
/*
* Nothing to do if the plugin has no latency or latency compensation is
* disabled.
*/
static int sox_ladspa_drain(sox_effect_t * effp, sox_sample_t *obuf, size_t *osamp)
{
priv_t * l_st = (priv_t *)effp->priv;
sox_sample_t *ibuf, *dbuf;
size_t isamp, dsamp;
int r;
if (l_st->out_latency == 0) {
*osamp = 0;
return SOX_SUCCESS;
}
/* feed some silence at the end to push the rest of the data out */
isamp = l_st->out_latency * effp->in_signal.channels;
dsamp = l_st->out_latency * effp->out_signal.channels;
ibuf = lsx_calloc(isamp, sizeof(sox_sample_t));
dbuf = lsx_calloc(dsamp, sizeof(sox_sample_t));
r = sox_ladspa_flow(effp, ibuf, dbuf, &isamp, &dsamp);
*osamp = min(dsamp, *osamp);
memcpy(obuf, dbuf, *osamp * sizeof(sox_sample_t));
free(ibuf);
free(dbuf);
return r == SOX_SUCCESS ? SOX_EOF : 0;
}
/*
* Do anything required when you stop reading samples.
* Don't close input file!
*/
static int sox_ladspa_stop(sox_effect_t * effp)
{
priv_t * l_st = (priv_t *)effp->priv;
size_t h;
for (h = 0; h < l_st->handle_count; h++) {
/* If needed, deactivate and cleanup the plugin */
if (l_st->desc->deactivate)
l_st->desc->deactivate(l_st->handles[h]);
if (l_st->desc->cleanup)
l_st->desc->cleanup(l_st->handles[h]);
}
free(l_st->handles);
l_st->handle_count = 0;
return SOX_SUCCESS;
}
static int sox_ladspa_kill(sox_effect_t * effp)
{
priv_t * l_st = (priv_t *)effp->priv;
free(l_st->control);
free(l_st->inputs);
free(l_st->outputs);
return SOX_SUCCESS;
}
static sox_effect_handler_t sox_ladspa_effect = {
"ladspa",
"MODULE [PLUGIN] [ARGUMENT...]",
SOX_EFF_MCHAN | SOX_EFF_CHAN | SOX_EFF_GAIN,
sox_ladspa_getopts,
sox_ladspa_start,
sox_ladspa_flow,
sox_ladspa_drain,
sox_ladspa_stop,
sox_ladspa_kill,
sizeof(priv_t)
};
const sox_effect_handler_t *lsx_ladspa_effect_fn(void)
{
return &sox_ladspa_effect;
}
#endif /* HAVE_LADSPA */

@ -1,603 +0,0 @@
/* ladspa.h
Linux Audio Developer's Simple Plugin API Version 1.1[LGPL].
Copyright (C) 2000-2002 Richard W.E. Furse, Paul Barton-Davis,
Stefan Westerfeld.
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 St, Fifth Floor, Boston, MA 02110-1301
USA. */
#ifndef LADSPA_INCLUDED
#define LADSPA_INCLUDED
#define LADSPA_VERSION "1.1"
#define LADSPA_VERSION_MAJOR 1
#define LADSPA_VERSION_MINOR 1
#ifdef __cplusplus
extern "C" {
#endif
/*****************************************************************************/
/* Overview:
There is a large number of synthesis packages in use or development
on the Linux platform at this time. This API (`The Linux Audio
Developer's Simple Plugin API') attempts to give programmers the
ability to write simple `plugin' audio processors in C/C++ and link
them dynamically (`plug') into a range of these packages (`hosts').
It should be possible for any host and any plugin to communicate
completely through this interface.
This API is deliberately short and simple. To achieve compatibility
with a range of promising Linux sound synthesis packages it
attempts to find the `greatest common divisor' in their logical
behaviour. Having said this, certain limiting decisions are
implicit, notably the use of a fixed type (LADSPA_Data) for all
data transfer and absence of a parameterised `initialisation'
phase. See below for the LADSPA_Data typedef.
Plugins are expected to distinguish between control and audio
data. Plugins have `ports' that are inputs or outputs for audio or
control data and each plugin is `run' for a `block' corresponding
to a short time interval measured in samples. Audio data is
communicated using arrays of LADSPA_Data, allowing a block of audio
to be processed by the plugin in a single pass. Control data is
communicated using single LADSPA_Data values. Control data has a
single value at the start of a call to the `run()' or `run_adding()'
function, and may be considered to remain this value for its
duration. The plugin may assume that all its input and output ports
have been connected to the relevant data location (see the
`connect_port()' function below) before it is asked to run.
Plugins will reside in shared object files suitable for dynamic
linking by dlopen() and family. The file will provide a number of
`plugin types' that can be used to instantiate actual plugins
(sometimes known as `plugin instances') that can be connected
together to perform tasks.
This API contains very limited error-handling. */
/*****************************************************************************/
/* Fundamental data type passed in and out of plugin. This data type
is used to communicate audio samples and control values. It is
assumed that the plugin will work sensibly given any numeric input
value although it may have a preferred range (see hints below).
For audio it is generally assumed that 1.0f is the `0dB' reference
amplitude and is a `normal' signal level. */
typedef float LADSPA_Data;
/*****************************************************************************/
/* Special Plugin Properties:
Optional features of the plugin type are encapsulated in the
LADSPA_Properties type. This is assembled by ORing individual
properties together. */
typedef int LADSPA_Properties;
/* Property LADSPA_PROPERTY_REALTIME indicates that the plugin has a
real-time dependency (e.g. listens to a MIDI device) and so its
output must not be cached or subject to significant latency. */
#define LADSPA_PROPERTY_REALTIME 0x1
/* Property LADSPA_PROPERTY_INPLACE_BROKEN indicates that the plugin
may cease to work correctly if the host elects to use the same data
location for both input and output (see connect_port()). This
should be avoided as enabling this flag makes it impossible for
hosts to use the plugin to process audio `in-place.' */
#define LADSPA_PROPERTY_INPLACE_BROKEN 0x2
/* Property LADSPA_PROPERTY_HARD_RT_CAPABLE indicates that the plugin
is capable of running not only in a conventional host but also in a
`hard real-time' environment. To qualify for this the plugin must
satisfy all of the following:
(1) The plugin must not use malloc(), free() or other heap memory
management within its run() or run_adding() functions. All new
memory used in run() must be managed via the stack. These
restrictions only apply to the run() function.
(2) The plugin will not attempt to make use of any library
functions with the exceptions of functions in the ANSI standard C
and C maths libraries, which the host is expected to provide.
(3) The plugin will not access files, devices, pipes, sockets, IPC
or any other mechanism that might result in process or thread
blocking.
(4) The plugin will take an amount of time to execute a run() or
run_adding() call approximately of form (A+B*SampleCount) where A
and B depend on the machine and host in use. This amount of time
may not depend on input signals or plugin state. The host is left
the responsibility to perform timings to estimate upper bounds for
A and B. */
#define LADSPA_PROPERTY_HARD_RT_CAPABLE 0x4
#define LADSPA_IS_REALTIME(x) ((x) & LADSPA_PROPERTY_REALTIME)
#define LADSPA_IS_INPLACE_BROKEN(x) ((x) & LADSPA_PROPERTY_INPLACE_BROKEN)
#define LADSPA_IS_HARD_RT_CAPABLE(x) ((x) & LADSPA_PROPERTY_HARD_RT_CAPABLE)
/*****************************************************************************/
/* Plugin Ports:
Plugins have `ports' that are inputs or outputs for audio or
data. Ports can communicate arrays of LADSPA_Data (for audio
inputs/outputs) or single LADSPA_Data values (for control
input/outputs). This information is encapsulated in the
LADSPA_PortDescriptor type which is assembled by ORing individual
properties together.
Note that a port must be an input or an output port but not both
and that a port must be a control or audio port but not both. */
typedef int LADSPA_PortDescriptor;
/* Property LADSPA_PORT_INPUT indicates that the port is an input. */
#define LADSPA_PORT_INPUT 0x1
/* Property LADSPA_PORT_OUTPUT indicates that the port is an output. */
#define LADSPA_PORT_OUTPUT 0x2
/* Property LADSPA_PORT_CONTROL indicates that the port is a control
port. */
#define LADSPA_PORT_CONTROL 0x4
/* Property LADSPA_PORT_AUDIO indicates that the port is a audio
port. */
#define LADSPA_PORT_AUDIO 0x8
#define LADSPA_IS_PORT_INPUT(x) ((x) & LADSPA_PORT_INPUT)
#define LADSPA_IS_PORT_OUTPUT(x) ((x) & LADSPA_PORT_OUTPUT)
#define LADSPA_IS_PORT_CONTROL(x) ((x) & LADSPA_PORT_CONTROL)
#define LADSPA_IS_PORT_AUDIO(x) ((x) & LADSPA_PORT_AUDIO)
/*****************************************************************************/
/* Plugin Port Range Hints:
The host may wish to provide a representation of data entering or
leaving a plugin (e.g. to generate a GUI automatically). To make
this more meaningful, the plugin should provide `hints' to the host
describing the usual values taken by the data.
Note that these are only hints. The host may ignore them and the
plugin must not assume that data supplied to it is meaningful. If
the plugin receives invalid input data it is expected to continue
to run without failure and, where possible, produce a sensible
output (e.g. a high-pass filter given a negative cutoff frequency
might switch to an all-pass mode).
Hints are meaningful for all input and output ports but hints for
input control ports are expected to be particularly useful.
More hint information is encapsulated in the
LADSPA_PortRangeHintDescriptor type which is assembled by ORing
individual hint types together. Hints may require further
LowerBound and UpperBound information.
All the hint information for a particular port is aggregated in the
LADSPA_PortRangeHint structure. */
typedef int LADSPA_PortRangeHintDescriptor;
/* Hint LADSPA_HINT_BOUNDED_BELOW indicates that the LowerBound field
of the LADSPA_PortRangeHint should be considered meaningful. The
value in this field should be considered the (inclusive) lower
bound of the valid range. If LADSPA_HINT_SAMPLE_RATE is also
specified then the value of LowerBound should be multiplied by the
sample rate. */
#define LADSPA_HINT_BOUNDED_BELOW 0x1
/* Hint LADSPA_HINT_BOUNDED_ABOVE indicates that the UpperBound field
of the LADSPA_PortRangeHint should be considered meaningful. The
value in this field should be considered the (inclusive) upper
bound of the valid range. If LADSPA_HINT_SAMPLE_RATE is also
specified then the value of UpperBound should be multiplied by the
sample rate. */
#define LADSPA_HINT_BOUNDED_ABOVE 0x2
/* Hint LADSPA_HINT_TOGGLED indicates that the data item should be
considered a Boolean toggle. Data less than or equal to zero should
be considered `off' or `false,' and data above zero should be
considered `on' or `true.' LADSPA_HINT_TOGGLED may not be used in
conjunction with any other hint except LADSPA_HINT_DEFAULT_0 or
LADSPA_HINT_DEFAULT_1. */
#define LADSPA_HINT_TOGGLED 0x4
/* Hint LADSPA_HINT_SAMPLE_RATE indicates that any bounds specified
should be interpreted as multiples of the sample rate. For
instance, a frequency range from 0Hz to the Nyquist frequency (half
the sample rate) could be requested by this hint in conjunction
with LowerBound = 0 and UpperBound = 0.5. Hosts that support bounds
at all must support this hint to retain meaning. */
#define LADSPA_HINT_SAMPLE_RATE 0x8
/* Hint LADSPA_HINT_LOGARITHMIC indicates that it is likely that the
user will find it more intuitive to view values using a logarithmic
scale. This is particularly useful for frequencies and gains. */
#define LADSPA_HINT_LOGARITHMIC 0x10
/* Hint LADSPA_HINT_INTEGER indicates that a user interface would
probably wish to provide a stepped control taking only integer
values. Any bounds set should be slightly wider than the actual
integer range required to avoid floating point rounding errors. For
instance, the integer set {0,1,2,3} might be described as [-0.1,
3.1]. */
#define LADSPA_HINT_INTEGER 0x20
/* The various LADSPA_HINT_HAS_DEFAULT_* hints indicate a `normal'
value for the port that is sensible as a default. For instance,
this value is suitable for use as an initial value in a user
interface or as a value the host might assign to a control port
when the user has not provided one. Defaults are encoded using a
mask so only one default may be specified for a port. Some of the
hints make use of lower and upper bounds, in which case the
relevant bound or bounds must be available and
LADSPA_HINT_SAMPLE_RATE must be applied as usual. The resulting
default must be rounded if LADSPA_HINT_INTEGER is present. Default
values were introduced in LADSPA v1.1. */
#define LADSPA_HINT_DEFAULT_MASK 0x3C0
/* This default values indicates that no default is provided. */
#define LADSPA_HINT_DEFAULT_NONE 0x0
/* This default hint indicates that the suggested lower bound for the
port should be used. */
#define LADSPA_HINT_DEFAULT_MINIMUM 0x40
/* This default hint indicates that a low value between the suggested
lower and upper bounds should be chosen. For ports with
LADSPA_HINT_LOGARITHMIC, this should be exp(log(lower) * 0.75 +
log(upper) * 0.25). Otherwise, this should be (lower * 0.75 + upper
* 0.25). */
#define LADSPA_HINT_DEFAULT_LOW 0x80
/* This default hint indicates that a middle value between the
suggested lower and upper bounds should be chosen. For ports with
LADSPA_HINT_LOGARITHMIC, this should be exp(log(lower) * 0.5 +
log(upper) * 0.5). Otherwise, this should be (lower * 0.5 + upper *
0.5). */
#define LADSPA_HINT_DEFAULT_MIDDLE 0xC0
/* This default hint indicates that a high value between the suggested
lower and upper bounds should be chosen. For ports with
LADSPA_HINT_LOGARITHMIC, this should be exp(log(lower) * 0.25 +
log(upper) * 0.75). Otherwise, this should be (lower * 0.25 + upper
* 0.75). */
#define LADSPA_HINT_DEFAULT_HIGH 0x100
/* This default hint indicates that the suggested upper bound for the
port should be used. */
#define LADSPA_HINT_DEFAULT_MAXIMUM 0x140
/* This default hint indicates that the number 0 should be used. Note
that this default may be used in conjunction with
LADSPA_HINT_TOGGLED. */
#define LADSPA_HINT_DEFAULT_0 0x200
/* This default hint indicates that the number 1 should be used. Note
that this default may be used in conjunction with
LADSPA_HINT_TOGGLED. */
#define LADSPA_HINT_DEFAULT_1 0x240
/* This default hint indicates that the number 100 should be used. */
#define LADSPA_HINT_DEFAULT_100 0x280
/* This default hint indicates that the Hz frequency of `concert A'
should be used. This will be 440 unless the host uses an unusual
tuning convention, in which case it may be within a few Hz. */
#define LADSPA_HINT_DEFAULT_440 0x2C0
#define LADSPA_IS_HINT_BOUNDED_BELOW(x) ((x) & LADSPA_HINT_BOUNDED_BELOW)
#define LADSPA_IS_HINT_BOUNDED_ABOVE(x) ((x) & LADSPA_HINT_BOUNDED_ABOVE)
#define LADSPA_IS_HINT_TOGGLED(x) ((x) & LADSPA_HINT_TOGGLED)
#define LADSPA_IS_HINT_SAMPLE_RATE(x) ((x) & LADSPA_HINT_SAMPLE_RATE)
#define LADSPA_IS_HINT_LOGARITHMIC(x) ((x) & LADSPA_HINT_LOGARITHMIC)
#define LADSPA_IS_HINT_INTEGER(x) ((x) & LADSPA_HINT_INTEGER)
#define LADSPA_IS_HINT_HAS_DEFAULT(x) ((x) & LADSPA_HINT_DEFAULT_MASK)
#define LADSPA_IS_HINT_DEFAULT_MINIMUM(x) (((x) & LADSPA_HINT_DEFAULT_MASK) \
== LADSPA_HINT_DEFAULT_MINIMUM)
#define LADSPA_IS_HINT_DEFAULT_LOW(x) (((x) & LADSPA_HINT_DEFAULT_MASK) \
== LADSPA_HINT_DEFAULT_LOW)
#define LADSPA_IS_HINT_DEFAULT_MIDDLE(x) (((x) & LADSPA_HINT_DEFAULT_MASK) \
== LADSPA_HINT_DEFAULT_MIDDLE)
#define LADSPA_IS_HINT_DEFAULT_HIGH(x) (((x) & LADSPA_HINT_DEFAULT_MASK) \
== LADSPA_HINT_DEFAULT_HIGH)
#define LADSPA_IS_HINT_DEFAULT_MAXIMUM(x) (((x) & LADSPA_HINT_DEFAULT_MASK) \
== LADSPA_HINT_DEFAULT_MAXIMUM)
#define LADSPA_IS_HINT_DEFAULT_0(x) (((x) & LADSPA_HINT_DEFAULT_MASK) \
== LADSPA_HINT_DEFAULT_0)
#define LADSPA_IS_HINT_DEFAULT_1(x) (((x) & LADSPA_HINT_DEFAULT_MASK) \
== LADSPA_HINT_DEFAULT_1)
#define LADSPA_IS_HINT_DEFAULT_100(x) (((x) & LADSPA_HINT_DEFAULT_MASK) \
== LADSPA_HINT_DEFAULT_100)
#define LADSPA_IS_HINT_DEFAULT_440(x) (((x) & LADSPA_HINT_DEFAULT_MASK) \
== LADSPA_HINT_DEFAULT_440)
typedef struct _LADSPA_PortRangeHint {
/* Hints about the port. */
LADSPA_PortRangeHintDescriptor HintDescriptor;
/* Meaningful when hint LADSPA_HINT_BOUNDED_BELOW is active. When
LADSPA_HINT_SAMPLE_RATE is also active then this value should be
multiplied by the relevant sample rate. */
LADSPA_Data LowerBound;
/* Meaningful when hint LADSPA_HINT_BOUNDED_ABOVE is active. When
LADSPA_HINT_SAMPLE_RATE is also active then this value should be
multiplied by the relevant sample rate. */
LADSPA_Data UpperBound;
} LADSPA_PortRangeHint;
/*****************************************************************************/
/* Plugin Handles:
This plugin handle indicates a particular instance of the plugin
concerned. It is valid to compare this to NULL (0 for C++) but
otherwise the host should not attempt to interpret it. The plugin
may use it to reference internal instance data. */
typedef void * LADSPA_Handle;
/*****************************************************************************/
/* Descriptor for a Type of Plugin:
This structure is used to describe a plugin type. It provides a
number of functions to examine the type, instantiate it, link it to
buffers and workspaces and to run it. */
typedef struct _LADSPA_Descriptor {
/* This numeric identifier indicates the plugin type
uniquely. Plugin programmers may reserve ranges of IDs from a
central body to avoid clashes. Hosts may assume that IDs are
below 0x1000000. */
unsigned long UniqueID;
/* This identifier can be used as a unique, case-sensitive
identifier for the plugin type within the plugin file. Plugin
types should be identified by file and label rather than by index
or plugin name, which may be changed in new plugin
versions. Labels must not contain white-space characters. */
const char * Label;
/* This indicates a number of properties of the plugin. */
LADSPA_Properties Properties;
/* This member points to the null-terminated name of the plugin
(e.g. "Sine Oscillator"). */
const char * Name;
/* This member points to the null-terminated string indicating the
maker of the plugin. This can be an empty string but not NULL. */
const char * Maker;
/* This member points to the null-terminated string indicating any
copyright applying to the plugin. If no Copyright applies the
string "None" should be used. */
const char * Copyright;
/* This indicates the number of ports (input AND output) present on
the plugin. */
unsigned long PortCount;
/* This member indicates an array of port descriptors. Valid indices
vary from 0 to PortCount-1. */
const LADSPA_PortDescriptor * PortDescriptors;
/* This member indicates an array of null-terminated strings
describing ports (e.g. "Frequency (Hz)"). Valid indices vary from
0 to PortCount-1. */
const char * const * PortNames;
/* This member indicates an array of range hints for each port (see
above). Valid indices vary from 0 to PortCount-1. */
const LADSPA_PortRangeHint * PortRangeHints;
/* This may be used by the plugin developer to pass any custom
implementation data into an instantiate call. It must not be used
or interpreted by the host. It is expected that most plugin
writers will not use this facility as LADSPA_Handle should be
used to hold instance data. */
void * ImplementationData;
/* This member is a function pointer that instantiates a plugin. A
handle is returned indicating the new plugin instance. The
instantiation function accepts a sample rate as a parameter. The
plugin descriptor from which this instantiate function was found
must also be passed. This function must return NULL if
instantiation fails.
Note that instance initialisation should generally occur in
activate() rather than here. */
LADSPA_Handle (*instantiate)(const struct _LADSPA_Descriptor * Descriptor,
unsigned long SampleRate);
/* This member is a function pointer that connects a port on an
instantiated plugin to a memory location at which a block of data
for the port will be read/written. The data location is expected
to be an array of LADSPA_Data for audio ports or a single
LADSPA_Data value for control ports. Memory issues will be
managed by the host. The plugin must read/write the data at these
locations every time run() or run_adding() is called and the data
present at the time of this connection call should not be
considered meaningful.
connect_port() may be called more than once for a plugin instance
to allow the host to change the buffers that the plugin is
reading or writing. These calls may be made before or after
activate() or deactivate() calls.
connect_port() must be called at least once for each port before
run() or run_adding() is called. When working with blocks of
LADSPA_Data the plugin should pay careful attention to the block
size passed to the run function as the block allocated may only
just be large enough to contain the block of samples.
Plugin writers should be aware that the host may elect to use the
same buffer for more than one port and even use the same buffer
for both input and output (see LADSPA_PROPERTY_INPLACE_BROKEN).
However, overlapped buffers or use of a single buffer for both
audio and control data may result in unexpected behaviour. */
void (*connect_port)(LADSPA_Handle Instance,
unsigned long Port,
LADSPA_Data * DataLocation);
/* This member is a function pointer that initialises a plugin
instance and activates it for use. This is separated from
instantiate() to aid real-time support and so that hosts can
reinitialise a plugin instance by calling deactivate() and then
activate(). In this case the plugin instance must reset all state
information dependent on the history of the plugin instance
except for any data locations provided by connect_port() and any
gain set by set_run_adding_gain(). If there is nothing for
activate() to do then the plugin writer may provide a NULL rather
than an empty function.
When present, hosts must call this function once before run() (or
run_adding()) is called for the first time. This call should be
made as close to the run() call as possible and indicates to
real-time plugins that they are now live. Plugins should not rely
on a prompt call to run() after activate(). activate() may not be
called again unless deactivate() is called first. Note that
connect_port() may be called before or after a call to
activate(). */
void (*activate)(LADSPA_Handle Instance);
/* This method is a function pointer that runs an instance of a
plugin for a block. Two parameters are required: the first is a
handle to the particular instance to be run and the second
indicates the block size (in samples) for which the plugin
instance may run.
Note that if an activate() function exists then it must be called
before run() or run_adding(). If deactivate() is called for a
plugin instance then the plugin instance may not be reused until
activate() has been called again.
If the plugin has the property LADSPA_PROPERTY_HARD_RT_CAPABLE
then there are various things that the plugin should not do
within the run() or run_adding() functions (see above). */
void (*run)(LADSPA_Handle Instance,
unsigned long SampleCount);
/* This method is a function pointer that runs an instance of a
plugin for a block. This has identical behaviour to run() except
in the way data is output from the plugin. When run() is used,
values are written directly to the memory areas associated with
the output ports. However when run_adding() is called, values
must be added to the values already present in the memory
areas. Furthermore, output values written must be scaled by the
current gain set by set_run_adding_gain() (see below) before
addition.
run_adding() is optional. When it is not provided by a plugin,
this function pointer must be set to NULL. When it is provided,
the function set_run_adding_gain() must be provided also. */
void (*run_adding)(LADSPA_Handle Instance,
unsigned long SampleCount);
/* This method is a function pointer that sets the output gain for
use when run_adding() is called (see above). If this function is
never called the gain is assumed to default to 1. Gain
information should be retained when activate() or deactivate()
are called.
This function should be provided by the plugin if and only if the
run_adding() function is provided. When it is absent this
function pointer must be set to NULL. */
void (*set_run_adding_gain)(LADSPA_Handle Instance,
LADSPA_Data Gain);
/* This is the counterpart to activate() (see above). If there is
nothing for deactivate() to do then the plugin writer may provide
a NULL rather than an empty function.
Hosts must deactivate all activated units after they have been
run() (or run_adding()) for the last time. This call should be
made as close to the last run() call as possible and indicates to
real-time plugins that they are no longer live. Plugins should
not rely on prompt deactivation. Note that connect_port() may be
called before or after a call to deactivate().
Deactivation is not similar to pausing as the plugin instance
will be reinitialised when activate() is called to reuse it. */
void (*deactivate)(LADSPA_Handle Instance);
/* Once an instance of a plugin has been finished with it can be
deleted using the following function. The instance handle passed
ceases to be valid after this call.
If activate() was called for a plugin instance then a
corresponding call to deactivate() must be made before cleanup()
is called. */
void (*cleanup)(LADSPA_Handle Instance);
} LADSPA_Descriptor;
/**********************************************************************/
/* Accessing a Plugin: */
/* The exact mechanism by which plugins are loaded is host-dependent,
however all most hosts will need to know is the name of shared
object file containing the plugin types. To allow multiple hosts to
share plugin types, hosts may wish to check for environment
variable LADSPA_PATH. If present, this should contain a
colon-separated path indicating directories that should be searched
(in order) when loading plugin types.
A plugin programmer must include a function called
"ladspa_descriptor" with the following function prototype within
the shared object file. This function will have C-style linkage (if
you are using C++ this is taken care of by the `extern "C"' clause
at the top of the file).
A host will find the plugin shared object file by one means or
another, find the ladspa_descriptor() function, call it, and
proceed from there.
Plugin types are accessed by index (not ID) using values from 0
upwards. Out of range indexes must result in this function
returning NULL, so the plugin count can be determined by checking
for the least index that results in NULL being returned. */
const LADSPA_Descriptor * ladspa_descriptor(unsigned long Index);
/* Datatype corresponding to the ladspa_descriptor() function. */
typedef const LADSPA_Descriptor *
(*LADSPA_Descriptor_Function)(unsigned long Index);
/**********************************************************************/
#ifdef __cplusplus
}
#endif
#endif /* LADSPA_INCLUDED */
/* EOF */

@ -1,129 +0,0 @@
/* Effect: loudness filter 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"
#include "dft_filter.h"
#include <string.h>
typedef struct {
dft_filter_priv_t base;
double delta, start;
int n;
} priv_t;
static int create(sox_effect_t * effp, int argc, char **argv)
{
priv_t * p = (priv_t *)effp->priv;
dft_filter_priv_t * b = &p->base;
b->filter_ptr = &b->filter;
p->delta = -10;
p->start = 65;
p->n = 1023;
--argc, ++argv;
do { /* break-able block */
NUMERIC_PARAMETER(delta,-50 , 15) /* FIXME expand range */
NUMERIC_PARAMETER(start, 50 , 75) /* FIXME expand range */
NUMERIC_PARAMETER(n ,127 ,2047)
} while (0);
p->n = 2 * p->n + 1;
return argc? lsx_usage(effp) : SOX_SUCCESS;
}
static double * make_filter(int n, double start, double delta, double rate)
{
static const struct {double f, af, lu, tf;} iso226_table[] = {
{ 20,0.532,-31.6,78.5},{ 25,0.506,-27.2,68.7},{ 31.5,0.480,-23.0,59.5},
{ 40,0.455,-19.1,51.1},{ 50,0.432,-15.9,44.0},{ 63,0.409,-13.0,37.5},
{ 80,0.387,-10.3,31.5},{ 100,0.367, -8.1,26.5},{ 125,0.349, -6.2,22.1},
{ 160,0.330, -4.5,17.9},{ 200,0.315, -3.1,14.4},{ 250,0.301, -2.0,11.4},
{ 315,0.288, -1.1, 8.6},{ 400,0.276, -0.4, 6.2},{ 500,0.267, 0.0, 4.4},
{ 630,0.259, 0.3, 3.0},{ 800,0.253, 0.5, 2.2},{ 1000,0.250, 0.0, 2.4},
{ 1250,0.246, -2.7, 3.5},{ 1600,0.244, -4.1, 1.7},{ 2000,0.243, -1.0,-1.3},
{ 2500,0.243, 1.7,-4.2},{ 3150,0.243, 2.5,-6.0},{ 4000,0.242, 1.2,-5.4},
{ 5000,0.242, -2.1,-1.5},{ 6300,0.245, -7.1, 6.0},{ 8000,0.254,-11.2,12.6},
{10000,0.271,-10.7,13.9},{12500,0.301, -3.1,12.3},
};
#define LEN (array_length(iso226_table) + 2)
#define SPL(phon, t) (10 / t.af * log10(4.47e-3 * (pow(10., .025 * (phon)) - \
1.15) + pow(.4 * pow(10., (t.tf + t.lu) / 10 - 9), t.af)) - t.lu + 94)
double fs[LEN], spl[LEN], d[LEN], * work, * h;
int i, work_len;
fs[0] = log(1.);
spl[0] = delta * .2;
for (i = 0; i < (int)LEN - 2; ++i) {
spl[i + 1] = SPL(start + delta, iso226_table[i]) -
SPL(start , iso226_table[i]);
fs[i + 1] = log(iso226_table[i].f);
}
fs[i + 1] = log(100000.);
spl[i + 1] = spl[0];
lsx_prepare_spline3(fs, spl, (int)LEN, HUGE_VAL, HUGE_VAL, d);
for (work_len = 8192; work_len < rate / 2; work_len <<= 1);
work = lsx_calloc(work_len, sizeof(*work));
h = lsx_calloc(n, sizeof(*h));
for (i = 0; i <= work_len / 2; ++i) {
double f = rate * i / work_len;
double spl1 = f < 1? spl[0] : lsx_spline3(fs, spl, d, (int)LEN, log(f));
work[i < work_len / 2 ? 2 * i : 1] = dB_to_linear(spl1);
}
lsx_safe_rdft(work_len, -1, work);
for (i = 0; i < n; ++i)
h[i] = work[(work_len - n / 2 + i) % work_len] * 2. / work_len;
lsx_apply_kaiser(h, n, lsx_kaiser_beta(40 + 2./3 * fabs(delta), .1));
free(work);
return h;
#undef SPL
#undef LEN
}
static int start(sox_effect_t * effp)
{
priv_t * p = (priv_t *) effp->priv;
dft_filter_t * f = p->base.filter_ptr;
if (p->delta == 0)
return SOX_EFF_NULL;
if (!f->num_taps) {
double * h = make_filter(p->n, p->start, p->delta, effp->in_signal.rate);
if (effp->global_info->plot != sox_plot_off) {
char title[100];
sprintf(title, "SoX effect: loudness %g (%g)", p->delta, p->start);
lsx_plot_fir(h, p->n, effp->in_signal.rate,
effp->global_info->plot, title, p->delta - 5, 0.);
return SOX_EOF;
}
lsx_set_dft_filter(f, h, p->n, p->n >> 1);
}
return lsx_dft_filter_effect_fn()->start(effp);
}
sox_effect_handler_t const * lsx_loudness_effect_fn(void)
{
static sox_effect_handler_t handler;
handler = *lsx_dft_filter_effect_fn();
handler.name = "loudness";
handler.usage = "[gain [ref]]";
handler.getopts = create;
handler.start = start;
handler.priv_size = sizeof(priv_t);
return &handler;
}

@ -1,21 +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
*/
#include "sox_i.h"
#include "raw.h"
RAW_FORMAT(lu, 8, SOX_FILE_BIT_REV, ULAW)

@ -1,524 +0,0 @@
/* multiband compander effect for SoX
* by Daniel Pouzzner <douzzer@mega.nu> 2002-Oct-8
*
* Compander code adapted from the SoX compand effect, by Nick Bailey
*
* SoX is Copyright 1999 Chris Bagwell And Nick Bailey This source code is
* freely redistributable and may be used for any purpose. This copyright
* notice must be maintained. Chris Bagwell And Nick Bailey are not
* responsible for the consequences of using this software.
*
*
* Usage:
* mcompand quoted_compand_args [crossover_frequency
* quoted_compand_args [...]]
*
* quoted_compand_args are as for the compand effect:
*
* attack1,decay1[,attack2,decay2...]
* in-dB1,out-dB1[,in-dB2,out-dB2...]
* [ gain [ initial-volume [ delay ] ] ]
*
* Beware a variety of headroom (clipping) bugaboos.
*
* Implementation details:
* The input is divided into bands using 4th order Linkwitz-Riley IIRs.
* This is akin to the crossover of a loudspeaker, and results in flat
* frequency response absent compander action.
*
* The outputs of the array of companders is summed, and sample truncation
* is done on the final sum.
*
* Modifications to the predictive compression code properly maintain
* alignment of the outputs of the array of companders when the companders
* have different prediction intervals (volume application delays). Note
* that the predictive mode of the limiter needs some TLC - in fact, a
* rewrite - since what's really useful is to assure that a waveform won't
* be clipped, by slewing the volume in advance so that the peak is at
* limit (or below, if there's a higher subsequent peak visible in the
* lookahead window) once it's reached. */
#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>
#include <stdlib.h>
#include "compandt.h"
#include "mcompand_xover.h"
typedef struct {
sox_compandt_t transfer_fn;
size_t expectedChannels; /* Also flags that channels aren't to be treated
individually when = 1 and input not mono */
double *attackRate; /* An array of attack rates */
double *decayRate; /* ... and of decay rates */
double *volume; /* Current "volume" of each channel */
double delay; /* Delay to apply before companding */
double topfreq; /* upper bound crossover frequency */
crossover_t filter;
sox_sample_t *delay_buf; /* Old samples, used for delay processing */
size_t delay_size; /* lookahead for this band (in samples) - function of delay, above */
ptrdiff_t delay_buf_ptr; /* Index into delay_buf */
size_t delay_buf_cnt; /* No. of active entries in delay_buf */
} comp_band_t;
typedef struct {
size_t nBands;
sox_sample_t *band_buf1, *band_buf2, *band_buf3;
size_t band_buf_len;
size_t delay_buf_size;/* Size of delay_buf in samples */
comp_band_t *bands;
char *arg; /* copy of current argument */
} priv_t;
/*
* Process options
*
* Don't do initialization now.
* The 'info' fields are not yet filled in.
*/
static int sox_mcompand_getopts_1(comp_band_t * l, size_t n, char **argv)
{
char *s;
size_t rates, i, commas;
/* Start by checking the attack and decay rates */
for (s = argv[0], commas = 0; *s; ++s)
if (*s == ',') ++commas;
if (commas % 2 == 0) /* There must be an even number of
attack/decay parameters */
{
lsx_fail("compander: Odd number of attack & decay rate parameters");
return (SOX_EOF);
}
rates = 1 + commas/2;
l->attackRate = lsx_malloc(sizeof(double) * rates);
l->decayRate = lsx_malloc(sizeof(double) * rates);
l->volume = lsx_malloc(sizeof(double) * rates);
l->expectedChannels = rates;
l->delay_buf = NULL;
/* Now tokenise the rates string and set up these arrays. Keep
them in seconds at the moment: we don't know the sample rate yet. */
s = strtok(argv[0], ","); i = 0;
do {
l->attackRate[i] = atof(s); s = strtok(NULL, ",");
l->decayRate[i] = atof(s); s = strtok(NULL, ",");
++i;
} while (s != NULL);
if (!lsx_compandt_parse(&l->transfer_fn, argv[1], n>2 ? argv[2] : 0))
return SOX_EOF;
/* Set the initial "volume" to be attibuted to the input channels.
Unless specified, choose 1.0 (maximum) otherwise clipping will
result if the user has seleced a long attack time */
for (i = 0; i < l->expectedChannels; ++i) {
double v = n>=4 ? pow(10.0, atof(argv[3])/20) : 1.0;
l->volume[i] = v;
/* If there is a delay, store it. */
if (n >= 5) l->delay = atof(argv[4]);
else l->delay = 0.0;
}
return (SOX_SUCCESS);
}
static int parse_subarg(char *s, char **subargv, size_t *subargc) {
char **ap;
char *s_p;
s_p = s;
*subargc = 0;
for (ap = subargv; (*ap = strtok(s_p, " \t")) != NULL;) {
s_p = NULL;
if (*subargc == 5) {
++*subargc;
break;
}
if (**ap != '\0') {
++ap;
++*subargc;
}
}
if (*subargc < 2 || *subargc > 5)
{
lsx_fail("Wrong number of parameters for the compander effect within mcompand; usage:\n"
"\tattack1,decay1{,attack2,decay2} [soft-knee-dB:]in-dB1[,out-dB1]{,in-dB2,out-dB2} [gain [initial-volume-dB [delay]]]\n"
"\twhere {} means optional and repeatable and [] means optional.\n"
"\tdB values are floating point or -inf'; times are in seconds.");
return (SOX_EOF);
} else
return SOX_SUCCESS;
}
static int getopts(sox_effect_t * effp, int argc, char **argv)
{
char *subargv[6], *cp;
size_t subargc, i;
priv_t * c = (priv_t *) effp->priv;
--argc, ++argv;
c->band_buf1 = c->band_buf2 = c->band_buf3 = 0;
c->band_buf_len = 0;
/* how many bands? */
if (! (argc&1)) {
lsx_fail("mcompand accepts only an odd number of arguments:\argc"
" mcompand quoted_compand_args [crossover_freq quoted_compand_args [...]]");
return SOX_EOF;
}
c->nBands = (argc+1)>>1;
c->bands = lsx_calloc(c->nBands, sizeof(comp_band_t));
for (i=0;i<c->nBands;++i) {
c->arg = lsx_strdup(argv[i<<1]);
if (parse_subarg(c->arg,subargv,&subargc) != SOX_SUCCESS)
return SOX_EOF;
if (sox_mcompand_getopts_1(&c->bands[i], subargc, &subargv[0]) != SOX_SUCCESS)
return SOX_EOF;
free(c->arg);
c->arg = NULL;
if (i == (c->nBands-1))
c->bands[i].topfreq = 0;
else {
c->bands[i].topfreq = lsx_parse_frequency(argv[(i<<1)+1],&cp);
if (*cp) {
lsx_fail("bad frequency in args to mcompand");
return SOX_EOF;
}
if ((i>0) && (c->bands[i].topfreq < c->bands[i-1].topfreq)) {
lsx_fail("mcompand crossover frequencies must be in ascending order.");
return SOX_EOF;
}
}
}
return SOX_SUCCESS;
}
/*
* Prepare processing.
* Do all initializations.
*/
static int start(sox_effect_t * effp)
{
priv_t * c = (priv_t *) effp->priv;
comp_band_t * l;
size_t i;
size_t band;
for (band=0;band<c->nBands;++band) {
l = &c->bands[band];
l->delay_size = c->bands[band].delay * effp->out_signal.rate * effp->out_signal.channels;
if (l->delay_size > c->delay_buf_size)
c->delay_buf_size = l->delay_size;
}
for (band=0;band<c->nBands;++band) {
l = &c->bands[band];
/* Convert attack and decay rates using number of samples */
for (i = 0; i < l->expectedChannels; ++i) {
if (l->attackRate[i] > 1.0/effp->out_signal.rate)
l->attackRate[i] = 1.0 -
exp(-1.0/(effp->out_signal.rate * l->attackRate[i]));
else
l->attackRate[i] = 1.0;
if (l->decayRate[i] > 1.0/effp->out_signal.rate)
l->decayRate[i] = 1.0 -
exp(-1.0/(effp->out_signal.rate * l->decayRate[i]));
else
l->decayRate[i] = 1.0;
}
/* Allocate the delay buffer */
if (c->delay_buf_size > 0)
l->delay_buf = lsx_calloc(sizeof(long), c->delay_buf_size);
l->delay_buf_ptr = 0;
l->delay_buf_cnt = 0;
if (l->topfreq != 0)
crossover_setup(effp, &l->filter, l->topfreq);
}
return (SOX_SUCCESS);
}
/*
* Update a volume value using the given sample
* value, the attack rate and decay rate
*/
static void doVolume(double *v, double samp, comp_band_t * l, size_t chan)
{
double s = samp/(~((sox_sample_t)1<<31));
double delta = s - *v;
if (delta > 0.0) /* increase volume according to attack rate */
*v += delta * l->attackRate[chan];
else /* reduce volume according to decay rate */
*v += delta * l->decayRate[chan];
}
static int sox_mcompand_flow_1(sox_effect_t * effp, priv_t * c, comp_band_t * l, const sox_sample_t *ibuf, sox_sample_t *obuf, size_t len, size_t filechans)
{
size_t idone, odone;
for (idone = 0, odone = 0; idone < len; ibuf += filechans) {
size_t chan;
/* Maintain the volume fields by simulating a leaky pump circuit */
if (l->expectedChannels == 1 && filechans > 1) {
/* User is expecting same compander for all channels */
double maxsamp = 0.0;
for (chan = 0; chan < filechans; ++chan) {
double rect = fabs((double)ibuf[chan]);
if (rect > maxsamp)
maxsamp = rect;
}
doVolume(&l->volume[0], maxsamp, l, (size_t) 0);
} else {
for (chan = 0; chan < filechans; ++chan)
doVolume(&l->volume[chan], fabs((double)ibuf[chan]), l, chan);
}
/* Volume memory is updated: perform compand */
for (chan = 0; chan < filechans; ++chan) {
int ch = l->expectedChannels > 1 ? chan : 0;
double level_in_lin = l->volume[ch];
double level_out_lin = lsx_compandt(&l->transfer_fn, level_in_lin);
double checkbuf;
if (c->delay_buf_size <= 0) {
checkbuf = ibuf[chan] * level_out_lin;
SOX_SAMPLE_CLIP_COUNT(checkbuf, effp->clips);
obuf[odone++] = checkbuf;
idone++;
} else {
/* FIXME: note that this lookahead algorithm is really lame:
the response to a peak is released before the peak
arrives. */
/* because volume application delays differ band to band, but
total delay doesn't, the volume is applied in an iteration
preceding that in which the sample goes to obuf, except in
the band(s) with the longest vol app delay.
the offset between delay_buf_ptr and the sample to apply
vol to, is a constant equal to the difference between this
band's delay and the longest delay of all the bands. */
if (l->delay_buf_cnt >= l->delay_size) {
checkbuf = l->delay_buf[(l->delay_buf_ptr + c->delay_buf_size - l->delay_size)%c->delay_buf_size] * level_out_lin;
SOX_SAMPLE_CLIP_COUNT(checkbuf, effp->clips);
l->delay_buf[(l->delay_buf_ptr + c->delay_buf_size - l->delay_size)%c->delay_buf_size] = checkbuf;
}
if (l->delay_buf_cnt >= c->delay_buf_size) {
obuf[odone] = l->delay_buf[l->delay_buf_ptr];
odone++;
idone++;
} else {
l->delay_buf_cnt++;
idone++; /* no "odone++" because we did not fill obuf[...] */
}
l->delay_buf[l->delay_buf_ptr++] = ibuf[chan];
l->delay_buf_ptr %= c->delay_buf_size;
}
}
}
if (idone != odone || idone != len) {
/* Emergency brake - will lead to memory corruption otherwise since we
cannot report back to flow() how many samples were consumed/emitted.
Additionally, flow() doesn't know how to handle diverging
sub-compander delays. */
lsx_fail("Using a compander delay within mcompand is currently not supported");
exit(1);
/* FIXME */
}
return (SOX_SUCCESS);
}
/*
* Processed signed long samples from ibuf to obuf.
* Return number of samples processed.
*/
static int flow(sox_effect_t * effp, const sox_sample_t *ibuf, sox_sample_t *obuf,
size_t *isamp, size_t *osamp) {
priv_t * c = (priv_t *) effp->priv;
comp_band_t * l;
size_t len = min(*isamp, *osamp);
size_t band, i;
sox_sample_t *abuf, *bbuf, *cbuf, *oldabuf, *ibuf_copy;
double out;
if (c->band_buf_len < len) {
c->band_buf1 = lsx_realloc(c->band_buf1,len*sizeof(sox_sample_t));
c->band_buf2 = lsx_realloc(c->band_buf2,len*sizeof(sox_sample_t));
c->band_buf3 = lsx_realloc(c->band_buf3,len*sizeof(sox_sample_t));
c->band_buf_len = len;
}
len -= len % effp->out_signal.channels;
ibuf_copy = lsx_malloc(*isamp * sizeof(sox_sample_t));
memcpy(ibuf_copy, ibuf, *isamp * sizeof(sox_sample_t));
/* split ibuf into bands using filters, pipe each band through sox_mcompand_flow_1, then add back together and write to obuf */
memset(obuf,0,len * sizeof *obuf);
for (band=0,abuf=ibuf_copy,bbuf=c->band_buf2,cbuf=c->band_buf1;band<c->nBands;++band) {
l = &c->bands[band];
if (l->topfreq)
crossover_flow(effp, &l->filter, abuf, bbuf, cbuf, len);
else {
bbuf = abuf;
abuf = cbuf;
}
if (abuf == ibuf_copy)
abuf = c->band_buf3;
(void)sox_mcompand_flow_1(effp, c,l,bbuf,abuf,len, (size_t)effp->out_signal.channels);
for (i=0;i<len;++i)
{
out = (double)obuf[i] + (double)abuf[i];
SOX_SAMPLE_CLIP_COUNT(out, effp->clips);
obuf[i] = out;
}
oldabuf = abuf;
abuf = cbuf;
cbuf = oldabuf;
}
*isamp = *osamp = len;
free(ibuf_copy);
return SOX_SUCCESS;
}
static int sox_mcompand_drain_1(sox_effect_t * effp, priv_t * c, comp_band_t * l, sox_sample_t *obuf, size_t maxdrain)
{
size_t done;
double out;
/*
* Drain out delay samples. Note that this loop does all channels.
*/
for (done = 0; done < maxdrain && l->delay_buf_cnt > 0; done++) {
out = obuf[done] + l->delay_buf[l->delay_buf_ptr++];
SOX_SAMPLE_CLIP_COUNT(out, effp->clips);
obuf[done] = out;
l->delay_buf_ptr %= c->delay_buf_size;
l->delay_buf_cnt--;
}
/* tell caller number of samples played */
return done;
}
/*
* Drain out compander delay lines.
*/
static int drain(sox_effect_t * effp, sox_sample_t *obuf, size_t *osamp)
{
size_t band, drained, mostdrained = 0;
priv_t * c = (priv_t *)effp->priv;
comp_band_t * l;
*osamp -= *osamp % effp->out_signal.channels;
memset(obuf,0,*osamp * sizeof *obuf);
for (band=0;band<c->nBands;++band) {
l = &c->bands[band];
drained = sox_mcompand_drain_1(effp, c,l,obuf,*osamp);
if (drained > mostdrained)
mostdrained = drained;
}
*osamp = mostdrained;
if (mostdrained)
return SOX_SUCCESS;
else
return SOX_EOF;
}
/*
* Clean up compander effect.
*/
static int stop(sox_effect_t * effp)
{
priv_t * c = (priv_t *) effp->priv;
comp_band_t * l;
size_t band;
free(c->band_buf1);
c->band_buf1 = NULL;
free(c->band_buf2);
c->band_buf2 = NULL;
free(c->band_buf3);
c->band_buf3 = NULL;
for (band = 0; band < c->nBands; band++) {
l = &c->bands[band];
free(l->delay_buf);
if (l->topfreq != 0)
free(l->filter.previous);
}
return SOX_SUCCESS;
}
static int lsx_kill(sox_effect_t * effp)
{
priv_t * c = (priv_t *) effp->priv;
comp_band_t * l;
size_t band;
for (band = 0; band < c->nBands; band++) {
l = &c->bands[band];
lsx_compandt_kill(&l->transfer_fn);
free(l->decayRate);
free(l->attackRate);
free(l->volume);
}
free(c->arg);
free(c->bands);
c->bands = NULL;
return SOX_SUCCESS;
}
const sox_effect_handler_t *lsx_mcompand_effect_fn(void)
{
static sox_effect_handler_t handler = {
"mcompand",
"quoted_compand_args [crossover_frequency[k] quoted_compand_args [...]]\n"
"\n"
"quoted_compand_args are as for the compand effect:\n"
"\n"
" attack1,decay1[,attack2,decay2...]\n"
" in-dB1,out-dB1[,in-dB2,out-dB2...]\n"
" [ gain [ initial-volume [ delay ] ] ]",
SOX_EFF_MCHAN | SOX_EFF_GAIN,
getopts, start, flow, drain, stop, lsx_kill, sizeof(priv_t)
};
return &handler;
}

@ -1,106 +0,0 @@
/* libSoX Compander Crossover Filter (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
*/
#define N 4 /* 4th order Linkwitz-Riley IIRs */
#define CONVOLVE _ _ _ _
typedef struct {double in, out_low, out_high;} previous_t[N * 2];
typedef struct {
previous_t * previous;
size_t pos;
double coefs[3 *(N+1)];
} crossover_t;
static void square_quadratic(char const * name, double const * x, double * y)
{
assert(N == 4);
y[0] = x[0] * x[0];
y[1] = 2 * x[0] * x[1];
y[2] = 2 * x[0] * x[2] + x[1] * x[1];
y[3] = 2 * x[1] * x[2];
y[4] = x[2] * x[2];
lsx_debug("%s=[%.16g %.16g %.16g %.16g %.16g];", name,
y[0], y[1], y[2], y[3], y[4]);
}
static int crossover_setup(sox_effect_t * effp, crossover_t * p, double frequency)
{
double w0 = 2 * M_PI * frequency / effp->in_signal.rate;
double Q = sqrt(.5), alpha = sin(w0)/(2*Q);
double x[9], norm;
int i;
if (w0 > M_PI) {
lsx_fail("frequency must not exceed half the sample-rate (Nyquist rate)");
return SOX_EOF;
}
x[0] = (1 - cos(w0))/2; /* Cf. filter_LPF in biquads.c */
x[1] = 1 - cos(w0);
x[2] = (1 - cos(w0))/2;
x[3] = (1 + cos(w0))/2; /* Cf. filter_HPF in biquads.c */
x[4] = -(1 + cos(w0));
x[5] = (1 + cos(w0))/2;
x[6] = 1 + alpha;
x[7] = -2*cos(w0);
x[8] = 1 - alpha;
for (norm = x[6], i = 0; i < 9; ++i) x[i] /= norm;
square_quadratic("lb", x , p->coefs);
square_quadratic("hb", x + 3, p->coefs + 5);
square_quadratic("a" , x + 6, p->coefs + 10);
p->previous = lsx_calloc(effp->in_signal.channels, sizeof(*p->previous));
return SOX_SUCCESS;
}
static int crossover_flow(sox_effect_t * effp, crossover_t * p, sox_sample_t
*ibuf, sox_sample_t *obuf_low, sox_sample_t *obuf_high, size_t len0)
{
double out_low, out_high;
size_t c, len = len0 / effp->in_signal.channels;
assert(len * effp->in_signal.channels == len0);
while (len--) {
p->pos = p->pos? p->pos - 1 : N - 1;
for (c = 0; c < effp->in_signal.channels; ++c) {
#define _ out_low += p->coefs[j] * p->previous[c][p->pos + j].in \
- p->coefs[2*N+2 + j] * p->previous[c][p->pos + j].out_low, ++j;
{
int j = 1;
out_low = p->coefs[0] * *ibuf;
CONVOLVE
assert(j == N+1);
*obuf_low++ = SOX_ROUND_CLIP_COUNT(out_low, effp->clips);
}
#undef _
#define _ out_high += p->coefs[j+N+1] * p->previous[c][p->pos + j].in \
- p->coefs[2*N+2 + j] * p->previous[c][p->pos + j].out_high, ++j;
{
int j = 1;
out_high = p->coefs[N+1] * *ibuf;
CONVOLVE
assert(j == N+1);
*obuf_high++ = SOX_ROUND_CLIP_COUNT(out_high, effp->clips);
}
p->previous[c][p->pos + N].in = p->previous[c][p->pos].in = *ibuf++;
p->previous[c][p->pos + N].out_low = p->previous[c][p->pos].out_low = out_low;
p->previous[c][p->pos + N].out_high = p->previous[c][p->pos].out_high = out_high;
}
}
return SOX_SUCCESS;
}

@ -1,171 +0,0 @@
/* libSoX MP3 utilities Copyright (c) 2007-9 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 <sys/stat.h>
#if defined(HAVE_LAME)
static void write_comments(sox_format_t * ft)
{
priv_t *p = (priv_t *) ft->priv;
const char* comment;
p->id3tag_init(p->gfp);
p->id3tag_set_pad(p->gfp, (size_t)ID3PADDING);
/* Note: id3tag_set_fieldvalue is not present in LAME 3.97, so we're using
the 3.97-compatible methods for all of the tags that 3.97 supported. */
/* FIXME: This is no more necessary, since support for LAME 3.97 has ended. */
if ((comment = sox_find_comment(ft->oob.comments, "Title")))
p->id3tag_set_title(p->gfp, comment);
if ((comment = sox_find_comment(ft->oob.comments, "Artist")))
p->id3tag_set_artist(p->gfp, comment);
if ((comment = sox_find_comment(ft->oob.comments, "Album")))
p->id3tag_set_album(p->gfp, comment);
if ((comment = sox_find_comment(ft->oob.comments, "Tracknumber")))
p->id3tag_set_track(p->gfp, comment);
if ((comment = sox_find_comment(ft->oob.comments, "Year")))
p->id3tag_set_year(p->gfp, comment);
if ((comment = sox_find_comment(ft->oob.comments, "Comment")))
p->id3tag_set_comment(p->gfp, comment);
if ((comment = sox_find_comment(ft->oob.comments, "Genre")))
{
if (p->id3tag_set_genre(p->gfp, comment))
lsx_warn("\"%s\" is not a recognized ID3v1 genre.", comment);
}
if ((comment = sox_find_comment(ft->oob.comments, "Discnumber")))
{
char* id3tag_buf = lsx_malloc(strlen(comment) + 6);
if (id3tag_buf)
{
sprintf(id3tag_buf, "TPOS=%s", comment);
p->id3tag_set_fieldvalue(p->gfp, id3tag_buf);
free(id3tag_buf);
}
}
}
#endif /* HAVE_LAME */
#ifdef HAVE_MAD_H
static unsigned long xing_frames(priv_t * p, struct mad_bitptr ptr, unsigned bitlen)
{
#define XING_MAGIC ( ('X' << 24) | ('i' << 16) | ('n' << 8) | 'g' )
if (bitlen >= 96 && p->mad_bit_read(&ptr, 32) == XING_MAGIC &&
(p->mad_bit_read(&ptr, 32) & 1 )) /* XING_FRAMES */
return p->mad_bit_read(&ptr, 32);
return 0;
}
static size_t mp3_duration(sox_format_t * ft)
{
priv_t * p = (priv_t *) ft->priv;
struct mad_stream mad_stream;
struct mad_header mad_header;
struct mad_frame mad_frame;
size_t initial_bitrate = 0; /* Initialised to prevent warning */
size_t tagsize = 0, consumed = 0, frames = 0;
sox_bool vbr = sox_false, depadded = sox_false;
size_t num_samples = 0;
p->mad_stream_init(&mad_stream);
p->mad_header_init(&mad_header);
p->mad_frame_init(&mad_frame);
do { /* Read data from the MP3 file */
int read, padding = 0;
size_t leftover = mad_stream.bufend - mad_stream.next_frame;
memmove(p->mp3_buffer, mad_stream.this_frame, leftover);
read = lsx_readbuf(ft, p->mp3_buffer + leftover, p->mp3_buffer_size - leftover);
if (read <= 0) {
lsx_debug("got exact duration by scan to EOF (frames=%" PRIuPTR " leftover=%" PRIuPTR ")", frames, leftover);
break;
}
for (; !depadded && padding < read && !p->mp3_buffer[padding]; ++padding);
depadded = sox_true;
p->mad_stream_buffer(&mad_stream, p->mp3_buffer + padding, leftover + read - padding);
while (sox_true) { /* Decode frame headers */
mad_stream.error = MAD_ERROR_NONE;
if (p->mad_header_decode(&mad_header, &mad_stream) == -1) {
if (mad_stream.error == MAD_ERROR_BUFLEN)
break; /* Normal behaviour; get some more data from the file */
if (!MAD_RECOVERABLE(mad_stream.error)) {
lsx_warn("unrecoverable MAD error");
break;
}
if (mad_stream.error == MAD_ERROR_LOSTSYNC) {
unsigned available = (mad_stream.bufend - mad_stream.this_frame);
tagsize = tagtype(mad_stream.this_frame, (size_t) available);
if (tagsize) { /* It's some ID3 tags, so just skip */
if (tagsize >= available) {
lsx_seeki(ft, (off_t)(tagsize - available), SEEK_CUR);
depadded = sox_false;
}
p->mad_stream_skip(&mad_stream, min(tagsize, available));
}
else lsx_warn("MAD lost sync");
}
else lsx_warn("recoverable MAD error");
continue; /* Not an audio frame */
}
num_samples += MAD_NSBSAMPLES(&mad_header) * 32;
consumed += mad_stream.next_frame - mad_stream.this_frame;
lsx_debug_more("bitrate=%lu", mad_header.bitrate);
if (!frames) {
initial_bitrate = mad_header.bitrate;
/* Get the precise frame count from the XING header if present */
mad_frame.header = mad_header;
if (p->mad_frame_decode(&mad_frame, &mad_stream) == -1)
if (!MAD_RECOVERABLE(mad_stream.error)) {
lsx_warn("unrecoverable MAD error");
break;
}
if ((frames = xing_frames(p, mad_stream.anc_ptr, mad_stream.anc_bitlen))) {
num_samples *= frames;
lsx_debug("got exact duration from XING frame count (%" PRIuPTR ")", frames);
break;
}
}
else vbr |= mad_header.bitrate != initial_bitrate;
/* If not VBR, we can time just a few frames then extrapolate */
if (++frames == 25 && !vbr) {
double frame_size = (double) consumed / frames;
size_t num_frames = (lsx_filelength(ft) - tagsize) / frame_size;
num_samples = num_samples / frames * num_frames;
lsx_debug("got approx. duration by CBR extrapolation");
break;
}
}
} while (mad_stream.error == MAD_ERROR_BUFLEN);
p->mad_frame_finish(&mad_frame);
mad_header_finish(&mad_header);
p->mad_stream_finish(&mad_stream);
lsx_rewind(ft);
return num_samples;
}
#endif /* HAVE_MAD_H */

File diff suppressed because it is too large Load Diff

@ -1,223 +0,0 @@
/* noiseprof - SoX Noise Profiling Effect.
*
* Written by Ian Turner (vectro@vectro.org)
* Copyright 1999 Ian Turner and others
*
* 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 "noisered.h"
#include <assert.h>
#include <string.h>
#include <errno.h>
typedef struct {
float *sum;
int *profilecount;
float *window;
} chandata_t;
typedef struct {
char* output_filename;
FILE* output_file;
chandata_t *chandata;
size_t bufdata;
} priv_t;
/*
* Get the filename, if any. We don't open it until sox_noiseprof_start.
*/
static int sox_noiseprof_getopts(sox_effect_t * effp, int argc, char **argv)
{
priv_t * data = (priv_t *) effp->priv;
--argc, ++argv;
if (argc == 1) {
data->output_filename = argv[0];
} else if (argc > 1)
return lsx_usage(effp);
return (SOX_SUCCESS);
}
/*
* Prepare processing.
* Do all initializations.
*/
static int sox_noiseprof_start(sox_effect_t * effp)
{
priv_t * data = (priv_t *) effp->priv;
unsigned channels = effp->in_signal.channels;
unsigned i;
/* Note: don't fall back to stderr if stdout is unavailable
* since we already use stderr for diagnostics. */
if (!data->output_filename || !strcmp(data->output_filename, "-")) {
if (effp->global_info->global_info->stdout_in_use_by) {
lsx_fail("stdout already in use by `%s'", effp->global_info->global_info->stdout_in_use_by);
return SOX_EOF;
}
effp->global_info->global_info->stdout_in_use_by = effp->handler.name;
data->output_file = stdout;
}
else if ((data->output_file = fopen(data->output_filename, "wb")) == NULL) {
lsx_fail("Couldn't open profile file %s: %s", data->output_filename, strerror(errno));
return SOX_EOF;
}
data->chandata = lsx_calloc(channels, sizeof(*(data->chandata)));
data->bufdata = 0;
for (i = 0; i < channels; i ++) {
data->chandata[i].sum = lsx_calloc(FREQCOUNT, sizeof(float));
data->chandata[i].profilecount = lsx_calloc(FREQCOUNT, sizeof(int));
data->chandata[i].window = lsx_calloc(WINDOWSIZE, sizeof(float));
}
return SOX_SUCCESS;
}
/* Collect statistics from the complete window on channel chan. */
static void collect_data(chandata_t* chan) {
float *out = lsx_calloc(FREQCOUNT, sizeof(float));
int i;
lsx_power_spectrum_f(WINDOWSIZE, chan->window, out);
for (i = 0; i < FREQCOUNT; i ++) {
if (out[i] > 0) {
float value = log(out[i]);
chan->sum[i] += value;
chan->profilecount[i] ++;
}
}
free(out);
}
/*
* Grab what we can from ibuf, and process if we have a whole window.
*/
static int sox_noiseprof_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 samp = min(*isamp, *osamp);
size_t chans = effp->in_signal.channels;
size_t i, j, n = min(samp / chans, WINDOWSIZE - p->bufdata);
memcpy(obuf, ibuf, n * chans * sizeof(*obuf)); /* Pass on audio unaffected */
*isamp = *osamp = n * chans;
/* Collect data for every channel. */
for (i = 0; i < chans; i ++) {
SOX_SAMPLE_LOCALS;
chandata_t * chan = &(p->chandata[i]);
for (j = 0; j < n; j ++)
chan->window[j + p->bufdata] =
SOX_SAMPLE_TO_FLOAT_32BIT(ibuf[i + j * chans],);
if (n + p->bufdata == WINDOWSIZE)
collect_data(chan);
}
p->bufdata += n;
assert(p->bufdata <= WINDOWSIZE);
if (p->bufdata == WINDOWSIZE)
p->bufdata = 0;
return SOX_SUCCESS;
}
/*
* Finish off the last window.
*/
static int sox_noiseprof_drain(sox_effect_t * effp, sox_sample_t *obuf UNUSED, size_t *osamp)
{
priv_t * data = (priv_t *) effp->priv;
int tracks = effp->in_signal.channels;
int i;
*osamp = 0;
if (data->bufdata == 0) {
return SOX_EOF;
}
for (i = 0; i < tracks; i ++) {
int j;
for (j = data->bufdata+1; j < WINDOWSIZE; j ++) {
data->chandata[i].window[j] = 0;
}
collect_data(&(data->chandata[i]));
}
if (data->bufdata == WINDOWSIZE || data->bufdata == 0)
return SOX_EOF;
else
return SOX_SUCCESS;
}
/*
* Print profile and clean up.
*/
static int sox_noiseprof_stop(sox_effect_t * effp)
{
priv_t * data = (priv_t *) effp->priv;
size_t i;
for (i = 0; i < effp->in_signal.channels; i ++) {
int j;
chandata_t* chan = &(data->chandata[i]);
fprintf(data->output_file, "Channel %lu: ", (unsigned long)i);
for (j = 0; j < FREQCOUNT; j ++) {
double r = chan->profilecount[j] != 0 ?
chan->sum[j] / chan->profilecount[j] : 0;
fprintf(data->output_file, "%s%f", j == 0 ? "" : ", ", r);
}
fprintf(data->output_file, "\n");
free(chan->sum);
free(chan->profilecount);
}
free(data->chandata);
if (data->output_file != stdout)
fclose(data->output_file);
return (SOX_SUCCESS);
}
static sox_effect_handler_t sox_noiseprof_effect = {
"noiseprof",
"[profile-file]",
SOX_EFF_MCHAN | SOX_EFF_MODIFY,
sox_noiseprof_getopts,
sox_noiseprof_start,
sox_noiseprof_flow,
sox_noiseprof_drain,
sox_noiseprof_stop,
NULL, sizeof(priv_t)
};
const sox_effect_handler_t *lsx_noiseprof_effect_fn(void)
{
return &sox_noiseprof_effect;
}

@ -1,357 +0,0 @@
/* noisered - Noise Reduction Effect.
*
* Written by Ian Turner (vectro@vectro.org)
*
* Copyright 1999 Ian Turner
* This source code is freely redistributable and may be used for
* any purpose. This copyright notice must be maintained.
* Authors are not responsible for the consequences of using this software.
*/
#include "noisered.h"
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#include <assert.h>
typedef struct {
float *window;
float *lastwindow;
float *noisegate;
float *smoothing;
} chandata_t;
/* Holds profile information */
typedef struct {
char* profile_filename;
float threshold;
chandata_t *chandata;
size_t bufdata;
} priv_t;
static void FFT(unsigned NumSamples,
int InverseTransform,
const float *RealIn, float *ImagIn, float *RealOut, float *ImagOut)
{
unsigned i;
double * work = malloc(2 * NumSamples * sizeof(*work));
for (i = 0; i < 2 * NumSamples; i += 2) {
work[i] = RealIn[i >> 1];
work[i + 1] = ImagIn? ImagIn[i >> 1] : 0;
}
lsx_safe_cdft(2 * (int)NumSamples, InverseTransform? -1 : 1, work);
if (InverseTransform) for (i = 0; i < 2 * NumSamples; i += 2) {
RealOut[i >> 1] = work[i] / NumSamples;
ImagOut[i >> 1] = work[i + 1] / NumSamples;
}
else for (i = 0; i < 2 * NumSamples; i += 2) {
RealOut[i >> 1] = work[i];
ImagOut[i >> 1] = work[i + 1];
}
free(work);
}
/*
* Get the options. Default file is stdin (if the audio
* input file isn't coming from there, of course!)
*/
static int sox_noisered_getopts(sox_effect_t * effp, int argc, char **argv)
{
priv_t * p = (priv_t *) effp->priv;
--argc, ++argv;
if (argc > 0) {
p->profile_filename = argv[0];
++argv;
--argc;
}
p->threshold = 0.5;
do { /* break-able block */
NUMERIC_PARAMETER(threshold, 0, 1);
} while (0);
return argc? lsx_usage(effp) : SOX_SUCCESS;
}
/*
* Prepare processing.
* Do all initializations.
*/
static int sox_noisered_start(sox_effect_t * effp)
{
priv_t * data = (priv_t *) effp->priv;
size_t fchannels = 0;
size_t channels = effp->in_signal.channels;
size_t i;
FILE * ifp = lsx_open_input_file(effp, data->profile_filename, sox_false);
if (!ifp)
return SOX_EOF;
data->chandata = lsx_calloc(channels, sizeof(*(data->chandata)));
data->bufdata = 0;
for (i = 0; i < channels; i ++) {
data->chandata[i].noisegate = lsx_calloc(FREQCOUNT, sizeof(float));
data->chandata[i].smoothing = lsx_calloc(FREQCOUNT, sizeof(float));
data->chandata[i].lastwindow = NULL;
}
while (1) {
unsigned long i1_ul;
size_t i1;
float f1;
if (2 != fscanf(ifp, " Channel %lu: %f", &i1_ul, &f1))
break;
i1 = i1_ul;
if (i1 != fchannels) {
lsx_fail("noisered: Got channel %lu, expected channel %lu.",
(unsigned long)i1, (unsigned long)fchannels);
return SOX_EOF;
}
data->chandata[fchannels].noisegate[0] = f1;
for (i = 1; i < FREQCOUNT; i ++) {
if (1 != fscanf(ifp, ", %f", &f1)) {
lsx_fail("noisered: Not enough data for channel %lu "
"(expected %d, got %lu)", (unsigned long)fchannels, FREQCOUNT, (unsigned long)i);
return SOX_EOF;
}
data->chandata[fchannels].noisegate[i] = f1;
}
fchannels ++;
}
if (fchannels != channels) {
lsx_fail("noisered: channel mismatch: %lu in input, %lu in profile.",
(unsigned long)channels, (unsigned long)fchannels);
return SOX_EOF;
}
if (ifp != stdin)
fclose(ifp);
effp->out_signal.length = SOX_UNKNOWN_LEN; /* TODO: calculate actual length */
return (SOX_SUCCESS);
}
/* Mangle a single window. Each output sample (except the first and last
* half-window) is the result of two distinct calls to this function,
* due to overlapping windows. */
static void reduce_noise(chandata_t* chan, float* window, double level)
{
float *inr, *ini, *outr, *outi, *power;
float *smoothing = chan->smoothing;
int i;
inr = lsx_calloc(WINDOWSIZE * 5, sizeof(float));
ini = inr + WINDOWSIZE;
outr = ini + WINDOWSIZE;
outi = outr + WINDOWSIZE;
power = outi + WINDOWSIZE;
for (i = 0; i < FREQCOUNT; i ++)
assert(smoothing[i] >= 0 && smoothing[i] <= 1);
memcpy(inr, window, WINDOWSIZE*sizeof(float));
FFT(WINDOWSIZE, 0, inr, NULL, outr, outi);
memcpy(inr, window, WINDOWSIZE*sizeof(float));
lsx_apply_hann_f(inr, WINDOWSIZE);
lsx_power_spectrum_f(WINDOWSIZE, inr, power);
for (i = 0; i < FREQCOUNT; i ++) {
float smooth;
float plog;
plog = log(power[i]);
if (power[i] != 0 && plog < chan->noisegate[i] + level*8.0)
smooth = 0.0;
else
smooth = 1.0;
smoothing[i] = smooth * 0.5 + smoothing[i] * 0.5;
}
/* Audacity says this code will eliminate tinkle bells.
* I have no idea what that means. */
for (i = 2; i < FREQCOUNT - 2; i ++) {
if (smoothing[i]>=0.5 &&
smoothing[i]<=0.55 &&
smoothing[i-1]<0.1 &&
smoothing[i-2]<0.1 &&
smoothing[i+1]<0.1 &&
smoothing[i+2]<0.1)
smoothing[i] = 0.0;
}
outr[0] *= smoothing[0];
outi[0] *= smoothing[0];
outr[FREQCOUNT-1] *= smoothing[FREQCOUNT-1];
outi[FREQCOUNT-1] *= smoothing[FREQCOUNT-1];
for (i = 1; i < FREQCOUNT-1; i ++) {
int j = WINDOWSIZE - i;
float smooth = smoothing[i];
outr[i] *= smooth;
outi[i] *= smooth;
outr[j] *= smooth;
outi[j] *= smooth;
}
FFT(WINDOWSIZE, 1, outr, outi, inr, ini);
lsx_apply_hann_f(inr, WINDOWSIZE);
memcpy(window, inr, WINDOWSIZE*sizeof(float));
for (i = 0; i < FREQCOUNT; i ++)
assert(smoothing[i] >= 0 && smoothing[i] <= 1);
free(inr);
}
/* Do window management once we have a complete window, including mangling
* the current window. */
static int process_window(sox_effect_t * effp, priv_t * data, unsigned chan_num, unsigned num_chans,
sox_sample_t *obuf, unsigned len) {
int j;
float* nextwindow;
int use = min(len, WINDOWSIZE)-min(len,(WINDOWSIZE/2));
chandata_t *chan = &(data->chandata[chan_num]);
int first = (chan->lastwindow == NULL);
SOX_SAMPLE_LOCALS;
if ((nextwindow = lsx_calloc(WINDOWSIZE, sizeof(float))) == NULL)
return SOX_EOF;
memcpy(nextwindow, chan->window+WINDOWSIZE/2,
sizeof(float)*(WINDOWSIZE/2));
reduce_noise(chan, chan->window, data->threshold);
if (!first) {
for (j = 0; j < use; j ++) {
float s = chan->window[j] + chan->lastwindow[WINDOWSIZE/2 + j];
obuf[chan_num + num_chans * j] =
SOX_FLOAT_32BIT_TO_SAMPLE(s, effp->clips);
}
free(chan->lastwindow);
} else {
for (j = 0; j < use; j ++) {
assert(chan->window[j] >= -1 && chan->window[j] <= 1);
obuf[chan_num + num_chans * j] =
SOX_FLOAT_32BIT_TO_SAMPLE(chan->window[j], effp->clips);
}
}
chan->lastwindow = chan->window;
chan->window = nextwindow;
return use;
}
/*
* Read in windows, and call process_window once we get a whole one.
*/
static int sox_noisered_flow(sox_effect_t * effp, const sox_sample_t *ibuf, sox_sample_t *obuf,
size_t *isamp, size_t *osamp)
{
priv_t * data = (priv_t *) effp->priv;
size_t samp = min(*isamp, *osamp);
size_t tracks = effp->in_signal.channels;
size_t track_samples = samp / tracks;
size_t ncopy = min(track_samples, WINDOWSIZE-data->bufdata);
size_t whole_window = (ncopy + data->bufdata == WINDOWSIZE);
int oldbuf = data->bufdata;
size_t i;
/* FIXME: Make this automatic for all effects */
assert(effp->in_signal.channels == effp->out_signal.channels);
if (whole_window)
data->bufdata = WINDOWSIZE/2;
else
data->bufdata += ncopy;
/* Reduce noise on every channel. */
for (i = 0; i < tracks; i ++) {
SOX_SAMPLE_LOCALS;
chandata_t* chan = &(data->chandata[i]);
size_t j;
if (chan->window == NULL)
chan->window = lsx_calloc(WINDOWSIZE, sizeof(float));
for (j = 0; j < ncopy; j ++)
chan->window[oldbuf + j] =
SOX_SAMPLE_TO_FLOAT_32BIT(ibuf[i + tracks * j], effp->clips);
if (!whole_window)
continue;
else
process_window(effp, data, (unsigned) i, (unsigned) tracks, obuf, (unsigned) (oldbuf + ncopy));
}
*isamp = tracks*ncopy;
if (whole_window)
*osamp = tracks*(WINDOWSIZE/2);
else
*osamp = 0;
return SOX_SUCCESS;
}
/*
* We have up to half a window left to dump.
*/
static int sox_noisered_drain(sox_effect_t * effp, sox_sample_t *obuf, size_t *osamp)
{
priv_t * data = (priv_t *)effp->priv;
unsigned i;
unsigned tracks = effp->in_signal.channels;
for (i = 0; i < tracks; i ++)
*osamp = process_window(effp, data, i, tracks, obuf, (unsigned) data->bufdata);
/* FIXME: This is very picky. osamp needs to be big enough to get all
* remaining data or it will be discarded.
*/
return (SOX_EOF);
}
/*
* Clean up.
*/
static int sox_noisered_stop(sox_effect_t * effp)
{
priv_t * data = (priv_t *) effp->priv;
size_t i;
for (i = 0; i < effp->in_signal.channels; i ++) {
chandata_t* chan = &(data->chandata[i]);
free(chan->lastwindow);
free(chan->window);
free(chan->smoothing);
free(chan->noisegate);
}
free(data->chandata);
return (SOX_SUCCESS);
}
static sox_effect_handler_t sox_noisered_effect = {
"noisered",
"[profile-file [amount]]",
SOX_EFF_MCHAN|SOX_EFF_LENGTH,
sox_noisered_getopts,
sox_noisered_start,
sox_noisered_flow,
sox_noisered_drain,
sox_noisered_stop,
NULL, sizeof(priv_t)
};
const sox_effect_handler_t *lsx_noisered_effect_fn(void)
{
return &sox_noisered_effect;
}

@ -1,26 +0,0 @@
/* noiseprof.h - Headers for SoX Noise Profiling Effect.
*
* Written by Ian Turner (vectro@vectro.org)
* Copyright 1999 Ian Turner and others
*
* 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 <math.h>
#define WINDOWSIZE 2048
#define HALFWINDOW (WINDOWSIZE / 2)
#define FREQCOUNT (HALFWINDOW + 1)

@ -1,235 +0,0 @@
/* libSoX Opus-in-Ogg sound format handler
* Copyright (C) 2013 John Stumpo <stump@jstump.com>
*
* Largely based on vorbis.c:
* libSoX Ogg Vorbis sound format handler
* Copyright 2001, Stan Seibert <indigo@aztec.asu.edu>
*
* Portions from oggenc, (c) Michael Smith <msmith@labyrinth.net.au>,
* ogg123, (c) Kenneth Arnold <kcarnold@yahoo.com>, and
* libvorbisfile (c) Xiphophorus Company
*
* May 9, 2001 - Stan Seibert (indigo@aztec.asu.edu)
* Ogg Vorbis handler initially written.
*
* July 5, 1991 - Skeleton file
* Copyright 1991 Lance Norskog And Sundry Contributors
* This source code is freely redistributable and may be used for
* any purpose. This copyright notice must be maintained.
* Lance Norskog And Sundry Contributors are not responsible for
* the consequences of using this software.
*/
#include "sox_i.h"
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <opusfile.h>
#define DEF_BUF_LEN 4096
#define BUF_ERROR -1
#define BUF_EOF 0
#define BUF_DATA 1
typedef struct {
/* Decoding data */
OggOpusFile *of;
char *buf;
size_t buf_len;
size_t start;
size_t end; /* Unsent data samples in buf[start] through buf[end-1] */
int current_section;
int eof;
} priv_t;
/******** Callback functions used in op_open_callbacks ************/
static int callback_read(void* ft_data, unsigned char* ptr, int nbytes)
{
sox_format_t* ft = (sox_format_t*)ft_data;
return lsx_readbuf(ft, ptr, (size_t)nbytes);
}
static int callback_seek(void* ft_data, opus_int64 off, int whence)
{
sox_format_t* ft = (sox_format_t*)ft_data;
int ret = ft->seekable ? lsx_seeki(ft, (off_t)off, whence) : -1;
if (ret == EBADF)
ret = -1;
return ret;
}
static int callback_close(void* ft_data UNUSED)
{
/* Do nothing so sox can close the file for us */
return 0;
}
static opus_int64 callback_tell(void* ft_data)
{
sox_format_t* ft = (sox_format_t*)ft_data;
return lsx_tell(ft);
}
/********************* End callbacks *****************************/
/*
* Do anything required before you start reading samples.
* Read file header.
* Find out sampling rate,
* size and encoding of samples,
* mono/stereo/quad.
*/
static int startread(sox_format_t * ft)
{
priv_t * vb = (priv_t *) ft->priv;
const OpusTags *ot;
int i;
OpusFileCallbacks callbacks = {
callback_read,
callback_seek,
callback_tell,
callback_close
};
/* Init the decoder */
vb->of = op_open_callbacks(ft, &callbacks, NULL, (size_t) 0, NULL);
if (vb->of == NULL) {
lsx_fail_errno(ft, SOX_EHDR, "Input not an Ogg Opus audio stream");
return (SOX_EOF);
}
/* Get info about the Opus stream */
ot = op_tags(vb->of, -1);
/* Record audio info */
ft->signal.rate = 48000; /* libopusfile always uses 48 kHz */
ft->encoding.encoding = SOX_ENCODING_OPUS;
ft->signal.channels = op_channel_count(vb->of, -1);
/* op_pcm_total doesn't work on non-seekable files so
* skip that step in that case. Also, it reports
* "frame"-ish results so we must * channels.
*/
if (ft->seekable)
ft->signal.length = op_pcm_total(vb->of, -1) * ft->signal.channels;
/* Record comments */
for (i = 0; i < ot->comments; i++)
sox_append_comment(&ft->oob.comments, ot->user_comments[i]);
/* Setup buffer */
vb->buf_len = DEF_BUF_LEN;
vb->buf_len -= vb->buf_len % (ft->signal.channels*2); /* 2 bytes per sample */
vb->buf = lsx_calloc(vb->buf_len, sizeof(char));
vb->start = vb->end = 0;
/* Fill in other info */
vb->eof = 0;
vb->current_section = -1;
return (SOX_SUCCESS);
}
/* Refill the buffer with samples. Returns BUF_EOF if the end of the
* Opus data was reached while the buffer was being filled,
* BUF_ERROR is something bad happens, and BUF_DATA otherwise */
static int refill_buffer(sox_format_t * ft)
{
priv_t * vb = (priv_t *) ft->priv;
int num_read;
if (vb->start == vb->end) /* Samples all played */
vb->start = vb->end = 0;
while (vb->end < vb->buf_len) {
num_read = op_read(vb->of, (opus_int16*) (vb->buf + vb->end),
(int) ((vb->buf_len - vb->end) / sizeof(opus_int16)),
&vb->current_section);
if (num_read == 0)
return (BUF_EOF);
else if (num_read == OP_HOLE)
lsx_warn("Warning: hole in stream; probably harmless");
else if (num_read < 0)
return (BUF_ERROR);
else
vb->end += num_read * sizeof(opus_int16) * ft->signal.channels;
}
return (BUF_DATA);
}
/*
* Read up to len samples from file.
* Convert to signed longs.
* Place in buf[].
* Return number of samples read.
*/
static size_t read_samples(sox_format_t * ft, sox_sample_t * buf, size_t len)
{
priv_t * vb = (priv_t *) ft->priv;
size_t i;
int ret;
sox_sample_t l;
for (i = 0; i < len; i++) {
if (vb->start == vb->end) {
if (vb->eof)
break;
ret = refill_buffer(ft);
if (ret == BUF_EOF || ret == BUF_ERROR) {
vb->eof = 1;
if (vb->end == 0)
break;
}
}
l = (vb->buf[vb->start + 1] << 24)
| (0xffffff & (vb->buf[vb->start] << 16));
*(buf + i) = l;
vb->start += 2;
}
return i;
}
/*
* Do anything required when you stop reading samples.
* Don't close input file!
*/
static int stopread(sox_format_t * ft)
{
priv_t * vb = (priv_t *) ft->priv;
free(vb->buf);
op_free(vb->of);
return (SOX_SUCCESS);
}
static int seek(sox_format_t * ft, uint64_t offset)
{
priv_t * vb = (priv_t *) ft->priv;
return op_pcm_seek(vb->of, (opus_int64)(offset / ft->signal.channels))? SOX_EOF:SOX_SUCCESS;
}
LSX_FORMAT_HANDLER(opus)
{
static const char *const names[] = {"opus", NULL};
static sox_format_handler_t handler = {SOX_LIB_VERSION_CODE,
"Xiph.org's Opus lossy compression", names, 0,
startread, read_samples, stopread,
NULL, NULL, NULL,
seek, NULL, NULL, sizeof(priv_t)
};
return &handler;
}

@ -1,446 +0,0 @@
/* Copyright 1997 Chris Bagwell And Sundry Contributors
* This source code is freely redistributable and may be used for
* any purpose. This copyright notice must be maintained.
* Chris Bagwell And Sundry Contributors are not
* responsible for the consequences of using this software.
*
* Direct to Open Sound System (OSS) sound driver
* OSS is a popular unix sound driver for Intel x86 unices (eg. Linux)
* and several other unixes (such as SunOS/Solaris).
* This driver is compatible with OSS original source that was called
* USS, Voxware and TASD.
*
* added by Chris Bagwell (cbagwell@sprynet.com) on 2/19/96
* based on info grabed from vplay.c in Voxware snd-utils-3.5 package.
* and on LINUX_PLAYER patches added by Greg Lee
* which was originally from Directo to Sound Blaster device driver (sbdsp.c).
* SBLAST patches by John T. Kohl.
*
* Changes:
*
* Nov. 26, 1999 Stan Brooks <stabro@megsinet.net>
* Moved initialization code common to startread and startwrite
* into a single function ossdspinit().
*
*/
#include "sox_i.h"
#include <stdlib.h>
#include <stdio.h>
#include <fcntl.h>
#ifdef HAVE_SYS_SOUNDCARD_H
#include <sys/soundcard.h>
#endif
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
/* these appear in the sys/soundcard.h of OSS 4.x, and in Linux's
* sound/core/oss/pcm_oss.c (2.6.24 and later), but are typically
* not included in system header files.
*/
#ifndef AFMT_S32_LE
#define AFMT_S32_LE 0x00001000
#endif
#ifndef AFMT_S32_BE
#define AFMT_S32_BE 0x00002000
#endif
#include <sys/ioctl.h>
typedef struct
{
char* pOutput;
unsigned cOutput;
int device;
unsigned sample_shift;
} priv_t;
/* common r/w initialization code */
static int ossinit(sox_format_t* ft)
{
int sampletype, samplesize;
int tmp, rc;
char const* szDevname;
priv_t* pPriv = (priv_t*)ft->priv;
if (ft->filename == 0 || ft->filename[0] == 0 || !strcasecmp("default", ft->filename))
{
szDevname = getenv("OSS_AUDIODEV");
if (szDevname != NULL)
{
lsx_report("Using device name from OSS_AUDIODEV environment variable: %s", szDevname);
}
else
{
szDevname = "/dev/dsp";
lsx_report("Using default OSS device name: %s", szDevname);
}
}
else
{
szDevname = ft->filename;
lsx_report("Using user-specified device name: %s", szDevname);
}
pPriv->device = open(
szDevname,
ft->mode == 'r' ? O_RDONLY : O_WRONLY);
if (pPriv->device < 0) {
lsx_fail_errno(ft, errno, "open failed for device: %s", szDevname);
return SOX_EOF;
}
if (ft->encoding.bits_per_sample == 8) {
sampletype = AFMT_U8;
samplesize = 8;
pPriv->sample_shift = 0;
if (ft->encoding.encoding == SOX_ENCODING_UNKNOWN)
ft->encoding.encoding = SOX_ENCODING_UNSIGNED;
if (ft->encoding.encoding != SOX_ENCODING_UNSIGNED) {
lsx_report("OSS driver only supports unsigned with bytes");
lsx_report("Forcing to unsigned");
ft->encoding.encoding = SOX_ENCODING_UNSIGNED;
}
}
else if (ft->encoding.bits_per_sample == 16) {
/* Attempt to use endian that user specified */
if (ft->encoding.reverse_bytes)
sampletype = (MACHINE_IS_BIGENDIAN) ? AFMT_S16_LE : AFMT_S16_BE;
else
sampletype = (MACHINE_IS_BIGENDIAN) ? AFMT_S16_BE : AFMT_S16_LE;
samplesize = 16;
pPriv->sample_shift = 1;
if (ft->encoding.encoding == SOX_ENCODING_UNKNOWN)
ft->encoding.encoding = SOX_ENCODING_SIGN2;
if (ft->encoding.encoding != SOX_ENCODING_SIGN2) {
lsx_report("OSS driver only supports signed with words");
lsx_report("Forcing to signed linear");
ft->encoding.encoding = SOX_ENCODING_SIGN2;
}
}
else if (ft->encoding.bits_per_sample == 32) {
/* Attempt to use endian that user specified */
if (ft->encoding.reverse_bytes)
sampletype = (MACHINE_IS_BIGENDIAN) ? AFMT_S32_LE : AFMT_S32_BE;
else
sampletype = (MACHINE_IS_BIGENDIAN) ? AFMT_S32_BE : AFMT_S32_LE;
samplesize = 32;
pPriv->sample_shift = 2;
if (ft->encoding.encoding == SOX_ENCODING_UNKNOWN)
ft->encoding.encoding = SOX_ENCODING_SIGN2;
if (ft->encoding.encoding != SOX_ENCODING_SIGN2) {
lsx_report("OSS driver only supports signed with words");
lsx_report("Forcing to signed linear");
ft->encoding.encoding = SOX_ENCODING_SIGN2;
}
}
else {
/* Attempt to use endian that user specified */
if (ft->encoding.reverse_bytes)
sampletype = (MACHINE_IS_BIGENDIAN) ? AFMT_S16_LE : AFMT_S16_BE;
else
sampletype = (MACHINE_IS_BIGENDIAN) ? AFMT_S16_BE : AFMT_S16_LE;
samplesize = 16;
pPriv->sample_shift = 1;
ft->encoding.bits_per_sample = 16;
ft->encoding.encoding = SOX_ENCODING_SIGN2;
lsx_report("OSS driver only supports bytes and words");
lsx_report("Forcing to signed linear word");
}
ft->signal.channels = 2;
if (ioctl(pPriv->device, (size_t) SNDCTL_DSP_RESET, 0) < 0)
{
lsx_fail_errno(ft,SOX_EOF,"Unable to reset OSS device %s. Possibly accessing an invalid file/device", szDevname);
return(SOX_EOF);
}
/* Query the supported formats and find the best match
*/
rc = ioctl(pPriv->device, SNDCTL_DSP_GETFMTS, &tmp);
if (rc == 0) {
if ((tmp & sampletype) == 0)
{
/* is 16-bit supported? */
if (samplesize == 16 && (tmp & (AFMT_S16_LE|AFMT_S16_BE)) == 0)
{
/* Must not like 16-bits, try 8-bits */
ft->encoding.bits_per_sample = 8;
ft->encoding.encoding = SOX_ENCODING_UNSIGNED;
lsx_report("OSS driver doesn't like signed words");
lsx_report("Forcing to unsigned bytes");
tmp = sampletype = AFMT_U8;
samplesize = 8;
pPriv->sample_shift = 0;
}
/* is 8-bit supported */
else if (samplesize == 8 && (tmp & AFMT_U8) == 0)
{
ft->encoding.bits_per_sample = 16;
ft->encoding.encoding = SOX_ENCODING_SIGN2;
lsx_report("OSS driver doesn't like unsigned bytes");
lsx_report("Forcing to signed words");
sampletype = (MACHINE_IS_BIGENDIAN) ? AFMT_S16_BE : AFMT_S16_LE;
samplesize = 16;
pPriv->sample_shift = 1;
}
/* determine which 16-bit format to use */
if (samplesize == 16 && (tmp & sampletype) == 0)
{
/* Either user requested something not supported
* or hardware doesn't support machine endian.
* Force to opposite as the above test showed
* it supports at least one of the two endians.
*/
sampletype = (sampletype == AFMT_S16_BE) ? AFMT_S16_LE : AFMT_S16_BE;
ft->encoding.reverse_bytes = !ft->encoding.reverse_bytes;
}
}
tmp = sampletype;
rc = ioctl(pPriv->device, SNDCTL_DSP_SETFMT, &tmp);
}
/* Give up and exit */
if (rc < 0 || tmp != sampletype)
{
lsx_fail_errno(ft,SOX_EOF,"Unable to set the sample size to %d", samplesize);
return (SOX_EOF);
}
tmp = 1;
if (ioctl(pPriv->device, SNDCTL_DSP_STEREO, &tmp) < 0 || tmp != 1)
{
lsx_warn("Couldn't set to stereo");
ft->signal.channels = 1;
}
tmp = ft->signal.rate;
if (ioctl(pPriv->device, SNDCTL_DSP_SPEED, &tmp) < 0 ||
(int)ft->signal.rate != tmp) {
/* If the rate the sound card is using is not within 1% of what
* the user specified then override the user setting.
* The only reason not to always override this is because of
* clock-rounding problems. Sound cards will sometimes use
* things like 44101 when you ask for 44100. No need overriding
* this and having strange output file rates for something that
* we can't hear anyways.
*/
if ((int)ft->signal.rate - tmp > (tmp * .01) ||
tmp - (int)ft->signal.rate > (tmp * .01))
ft->signal.rate = tmp;
}
if (ioctl(pPriv->device, (size_t) SNDCTL_DSP_SYNC, NULL) < 0) {
lsx_fail_errno(ft,SOX_EOF,"Unable to sync dsp");
return (SOX_EOF);
}
if (ft->mode == 'r') {
pPriv->cOutput = 0;
pPriv->pOutput = NULL;
} else {
size_t cbOutput = sox_globals.bufsiz;
pPriv->cOutput = cbOutput >> pPriv->sample_shift;
pPriv->pOutput = lsx_malloc(cbOutput);
}
return(SOX_SUCCESS);
}
static int ossstop(sox_format_t* ft)
{
priv_t* pPriv = (priv_t*)ft->priv;
if (pPriv->device >= 0) {
close(pPriv->device);
}
if (pPriv->pOutput) {
free(pPriv->pOutput);
}
return SOX_SUCCESS;
}
static size_t ossread(sox_format_t* ft, sox_sample_t* pOutput, size_t cOutput)
{
priv_t* pPriv = (priv_t*)ft->priv;
char* pbOutput = (char*)pOutput;
size_t cbOutputLeft = cOutput << pPriv->sample_shift;
size_t i, cRead;
int cbRead;
SOX_SAMPLE_LOCALS;
LSX_USE_VAR(sox_macro_temp_double);
while (cbOutputLeft) {
cbRead = read(pPriv->device, pbOutput, cbOutputLeft);
if (cbRead <= 0) {
if (cbRead < 0) {
lsx_fail_errno(ft, errno, "Error reading from device");
return 0;
}
break;
}
cbOutputLeft -= cbRead;
pbOutput += cbRead;
}
/* Convert in-place (backwards) */
cRead = cOutput - (cbOutputLeft >> pPriv->sample_shift);
if (ft->encoding.reverse_bytes) {
switch (pPriv->sample_shift)
{
case 0:
for (i = cRead; i != 0; i--) {
pOutput[i - 1] = SOX_UNSIGNED_8BIT_TO_SAMPLE(
((sox_uint8_t*)pOutput)[i - 1],
dummy);
}
break;
case 1:
for (i = cRead; i != 0; i--) {
pOutput[i - 1] = SOX_SIGNED_16BIT_TO_SAMPLE(
lsx_swapw(((sox_int16_t*)pOutput)[i - 1]),
dummy);
}
break;
case 2:
for (i = cRead; i != 0; i--) {
pOutput[i - 1] = SOX_SIGNED_32BIT_TO_SAMPLE(
lsx_swapdw(((sox_int32_t*)pOutput)[i - 1]),
dummy);
}
break;
}
} else {
switch (pPriv->sample_shift)
{
case 0:
for (i = cRead; i != 0; i--) {
pOutput[i - 1] = SOX_UNSIGNED_8BIT_TO_SAMPLE(
((sox_uint8_t*)pOutput)[i - 1],
dummy);
}
break;
case 1:
for (i = cRead; i != 0; i--) {
pOutput[i - 1] = SOX_SIGNED_16BIT_TO_SAMPLE(
((sox_int16_t*)pOutput)[i - 1],
dummy);
}
break;
case 2:
for (i = cRead; i != 0; i--) {
pOutput[i - 1] = SOX_SIGNED_32BIT_TO_SAMPLE(
((sox_int32_t*)pOutput)[i - 1],
dummy);
}
break;
}
}
return cRead;
}
static size_t osswrite(
sox_format_t* ft,
const sox_sample_t* pInput,
size_t cInput)
{
priv_t* pPriv = (priv_t*)ft->priv;
size_t cInputRemaining = cInput;
unsigned cClips = 0;
SOX_SAMPLE_LOCALS;
while (cInputRemaining) {
size_t cStride;
size_t i;
size_t cbStride;
int cbWritten;
cStride = cInputRemaining;
if (cStride > pPriv->cOutput) {
cStride = pPriv->cOutput;
}
if (ft->encoding.reverse_bytes)
{
switch (pPriv->sample_shift)
{
case 0:
for (i = 0; i != cStride; i++) {
((sox_uint8_t*)pPriv->pOutput)[i] =
SOX_SAMPLE_TO_UNSIGNED_8BIT(pInput[i], cClips);
}
break;
case 1:
for (i = 0; i != cStride; i++) {
sox_int16_t s16 = SOX_SAMPLE_TO_SIGNED_16BIT(pInput[i], cClips);
((sox_int16_t*)pPriv->pOutput)[i] = lsx_swapw(s16);
}
break;
case 2:
for (i = 0; i != cStride; i++) {
((sox_int32_t*)pPriv->pOutput)[i] =
lsx_swapdw(SOX_SAMPLE_TO_SIGNED_32BIT(pInput[i], cClips));
}
break;
}
} else {
switch (pPriv->sample_shift)
{
case 0:
for (i = 0; i != cStride; i++) {
((sox_uint8_t*)pPriv->pOutput)[i] =
SOX_SAMPLE_TO_UNSIGNED_8BIT(pInput[i], cClips);
}
break;
case 1:
for (i = 0; i != cStride; i++) {
((sox_int16_t*)pPriv->pOutput)[i] =
SOX_SAMPLE_TO_SIGNED_16BIT(pInput[i], cClips);
}
break;
case 2:
for (i = 0; i != cStride; i++) {
((sox_int32_t*)pPriv->pOutput)[i] =
SOX_SAMPLE_TO_SIGNED_32BIT(pInput[i], cClips);
}
break;
}
}
cbStride = cStride << pPriv->sample_shift;
i = 0;
do {
cbWritten = write(pPriv->device, &pPriv->pOutput[i], cbStride - i);
i += cbWritten;
if (cbWritten <= 0) {
lsx_fail_errno(ft, errno, "Error writing to device");
return 0;
}
} while (i != cbStride);
cInputRemaining -= cStride;
pInput += cStride;
}
return cInput;
}
LSX_FORMAT_HANDLER(oss)
{
static char const* const names[] = {"ossdsp", "oss", NULL};
static unsigned const write_encodings[] = {
SOX_ENCODING_SIGN2, 32, 16, 0,
SOX_ENCODING_UNSIGNED, 8, 0,
0};
static sox_format_handler_t const handler = {SOX_LIB_VERSION_CODE,
"Open Sound System device driver for unix-like systems",
names, SOX_FILE_DEVICE | SOX_FILE_NOSTDIO,
ossinit, ossread, ossstop,
ossinit, osswrite, ossstop,
NULL, write_encodings, NULL, sizeof(priv_t)
};
return &handler;
}

@ -1,71 +0,0 @@
/* libSoX effect: Overdrive (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 {
double gain, colour, last_in, last_out, b0, b1, a1;
} priv_t;
static int create(sox_effect_t * effp, int argc, char * * argv)
{
priv_t * p = (priv_t *)effp->priv;
--argc, ++argv;
p->gain = p->colour = 20;
do {
NUMERIC_PARAMETER(gain, 0, 100)
NUMERIC_PARAMETER(colour, 0, 100)
} while (0);
p->gain = dB_to_linear(p->gain);
p->colour /= 200;
return argc? lsx_usage(effp) : SOX_SUCCESS;
}
static int start(sox_effect_t * effp)
{
priv_t * p = (priv_t *)effp->priv;
if (p->gain == 1)
return SOX_EFF_NULL;
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 dummy = 0, len = *isamp = *osamp = min(*isamp, *osamp);
while (len--) {
SOX_SAMPLE_LOCALS;
double d = SOX_SAMPLE_TO_FLOAT_64BIT(*ibuf++, dummy), d0 = d;
d *= p->gain;
d += p->colour;
d = d < -1? -2./3 : d > 1? 2./3 : d - d * d * d * (1./3);
p->last_out = d - p->last_in + .995 * p->last_out;
p->last_in = d;
*obuf++ = SOX_FLOAT_64BIT_TO_SAMPLE(d0 * .5 + p->last_out * .75, dummy);
}
return SOX_SUCCESS;
}
sox_effect_handler_t const * lsx_overdrive_effect_fn(void)
{
static sox_effect_handler_t handler = {"overdrive", "[gain [colour]]",
SOX_EFF_GAIN, create, start, flow, NULL, NULL, NULL, sizeof(priv_t)};
return &handler;
}

@ -1,180 +0,0 @@
/* libSoX effect: Pad With Silence (c) 2006 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 {
unsigned npads; /* Number of pads requested */
struct {
char * str; /* Command-line argument to parse for this pad */
uint64_t start; /* Start padding when in_pos equals this */
uint64_t pad; /* Number of samples to pad */
} * pads;
uint64_t in_pos; /* Number of samples read from the input stream */
unsigned pads_pos; /* Number of pads completed so far */
uint64_t pad_pos; /* Number of samples through the current pad */
} priv_t;
static int parse(sox_effect_t * effp, char * * argv, sox_rate_t rate)
{
priv_t * p = (priv_t *)effp->priv;
char const * next;
unsigned i;
uint64_t last_seen = 0;
const uint64_t in_length = argv ? 0 :
(effp->in_signal.length != SOX_UNKNOWN_LEN ?
effp->in_signal.length / effp->in_signal.channels : SOX_UNKNOWN_LEN);
for (i = 0; i < p->npads; ++i) {
if (argv) /* 1st parse only */
p->pads[i].str = lsx_strdup(argv[i]);
next = lsx_parsesamples(rate, p->pads[i].str, &p->pads[i].pad, 't');
if (next == NULL) break;
if (*next == '\0')
p->pads[i].start = i? UINT64_MAX : 0;
else {
if (*next != '@') break;
next = lsx_parseposition(rate, next+1, argv ? NULL : &p->pads[i].start,
last_seen, in_length, '=');
if (next == NULL || *next != '\0') break;
last_seen = p->pads[i].start;
if (p->pads[i].start == SOX_UNKNOWN_LEN)
p->pads[i].start = UINT64_MAX; /* currently the same value, but ... */
}
if (!argv) {
/* Do this check only during the second pass when the actual
sample rate is known, otherwise it might fail on legal
commands like
pad 1@0.5 1@30000s
if the rate is, e.g., 48k. */
if (i > 0 && p->pads[i].start <= p->pads[i-1].start) break;
}
}
if (i < p->npads)
return lsx_usage(effp);
return SOX_SUCCESS;
}
static int create(sox_effect_t * effp, int argc, char * * argv)
{
priv_t * p = (priv_t *)effp->priv;
--argc, ++argv;
p->npads = argc;
p->pads = lsx_calloc(p->npads, sizeof(*p->pads));
return parse(effp, argv, 1e5); /* No rate yet; parse with dummy */
}
static int start(sox_effect_t * effp)
{
priv_t * p = (priv_t *)effp->priv;
unsigned i;
/* Re-parse now rate is known */
if (parse(effp, 0, effp->in_signal.rate) != SOX_SUCCESS)
return SOX_EOF;
if ((effp->out_signal.length = effp->in_signal.length) != SOX_UNKNOWN_LEN) {
for (i = 0; i < p->npads; ++i)
effp->out_signal.length +=
p->pads[i].pad * effp->in_signal.channels;
/* Check that the last pad position (except for "at the end")
is within bounds. */
i = p->npads;
if (i > 0 && p->pads[i-1].start == UINT64_MAX)
i--;
if (i > 0 &&
p->pads[i-1].start * effp->in_signal.channels
> effp->in_signal.length)
{
lsx_fail("pad position after end of audio");
return SOX_EOF;
}
}
p->in_pos = p->pad_pos = p->pads_pos = 0;
for (i = 0; i < p->npads; ++i)
if (p->pads[i].pad)
return SOX_SUCCESS;
return SOX_EFF_NULL;
}
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, idone = 0, odone = 0;
*isamp /= effp->in_signal.channels;
*osamp /= effp->in_signal.channels;
do {
/* Copying: */
for (; idone < *isamp && odone < *osamp && !(p->pads_pos != p->npads && p->in_pos == p->pads[p->pads_pos].start); ++idone, ++odone, ++p->in_pos)
for (c = 0; c < effp->in_signal.channels; ++c) *obuf++ = *ibuf++;
/* Padding: */
if (p->pads_pos != p->npads && p->in_pos == p->pads[p->pads_pos].start) {
for (; odone < *osamp && p->pad_pos < p->pads[p->pads_pos].pad; ++odone, ++p->pad_pos)
for (c = 0; c < effp->in_signal.channels; ++c) *obuf++ = 0;
if (p->pad_pos == p->pads[p->pads_pos].pad) { /* Move to next pad? */
++p->pads_pos;
p->pad_pos = 0;
}
}
} while (idone < *isamp && odone < *osamp);
*isamp = idone * effp->in_signal.channels;
*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;
if (p->pads_pos != p->npads && p->in_pos != p->pads[p->pads_pos].start)
p->in_pos = UINT64_MAX; /* Invoke the final pad (with no given start) */
return flow(effp, 0, obuf, &isamp, osamp);
}
static int stop(sox_effect_t * effp)
{
priv_t * p = (priv_t *)effp->priv;
if (p->pads_pos != p->npads)
lsx_warn("Input audio too short; pads not applied: %u", p->npads-p->pads_pos);
return SOX_SUCCESS;
}
static int lsx_kill(sox_effect_t * effp)
{
priv_t * p = (priv_t *)effp->priv;
unsigned i;
for (i = 0; i < p->npads; ++i)
free(p->pads[i].str);
free(p->pads);
return SOX_SUCCESS;
}
sox_effect_handler_t const * lsx_pad_effect_fn(void)
{
static sox_effect_handler_t handler = {
"pad", "{length[@position]}", SOX_EFF_MCHAN|SOX_EFF_LENGTH|SOX_EFF_MODIFY,
create, start, flow, drain, stop, lsx_kill, sizeof(priv_t)
};
return &handler;
}

@ -1,31 +0,0 @@
/* libSoX file format: PAF 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"
LSX_FORMAT_HANDLER(paf)
{
static char const * const names[] = {"paf", NULL};
static unsigned const write_encodings[] = {SOX_ENCODING_SIGN2, 24, 16, 8,0,0};
static sox_format_handler_t handler;
handler = *lsx_sndfile_format_fn();
handler.description =
"Ensoniq PARIS digital audio editing system (big endian)";
handler.names = names;
handler.write_formats = write_encodings;
return &handler;
}

@ -1,147 +0,0 @@
/* Effect: phaser 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: August 24, 1998
*
* * gain-in +---+ * gain-out
* ibuff ----------->| |----------------------------------> obuff
* | + | * decay
* | |<------------+
* +---+ _______ |
* | | | |
* +---| delay |---+
* |_______|
* /|\
* |
* +---------------+ +------------------+
* | Delay control |<-----| modulation speed |
* +---------------+ +------------------+
*
* The delay is controled by a sine or triangle modulation.
*
* Usage:
* phaser gain-in gain-out delay decay speed [ -s | -t ]
*
* Where:
* gain-in, decay : 0.0 .. 1.0 volume
* gain-out : 0.0 .. volume
* delay : 0.0 .. 5.0 msec
* speed : 0.1 .. 2.0 Hz modulation speed
* -s : modulation by sine (default)
* -t : modulation by triangle
*
* Note:
* When decay is close to 1.0, the samples may begin clipping or the output
* can saturate! Hint:
* in-gain < (1 - decay * decay)
* 1 / out-gain > gain-in / (1 - decay)
*/
#include "sox_i.h"
#include <string.h>
typedef struct {
double in_gain, out_gain, delay_ms, decay, mod_speed;
lsx_wave_t mod_type;
int * mod_buf;
size_t mod_buf_len;
int mod_pos;
double * delay_buf;
size_t delay_buf_len;
int delay_pos;
} priv_t;
static int getopts(sox_effect_t * effp, int argc, char * * argv)
{
priv_t * p = (priv_t *) effp->priv;
char chars[2];
/* Set non-zero defaults: */
p->in_gain = .4;
p->out_gain = .74;
p->delay_ms = 3.;
p->decay = .4;
p->mod_speed = .5;
--argc, ++argv;
do { /* break-able block */
NUMERIC_PARAMETER(in_gain , .0, 1)
NUMERIC_PARAMETER(out_gain , .0, 1e9)
NUMERIC_PARAMETER(delay_ms , .0, 5)
NUMERIC_PARAMETER(decay , .0, .99)
NUMERIC_PARAMETER(mod_speed, .1, 2)
} while (0);
if (argc && sscanf(*argv, "-%1[st]%c", chars, chars + 1) == 1) {
p->mod_type = *chars == 's'? SOX_WAVE_SINE : SOX_WAVE_TRIANGLE;
--argc, ++argv;
}
if (p->in_gain > (1 - p->decay * p->decay))
lsx_warn("warning: gain-in might cause clipping");
if (p->in_gain / (1 - p->decay) > 1 / p->out_gain)
lsx_warn("warning: gain-out might cause clipping");
return argc? lsx_usage(effp) : SOX_SUCCESS;
}
static int start(sox_effect_t * effp)
{
priv_t * p = (priv_t *) effp->priv;
p->delay_buf_len = p->delay_ms * .001 * effp->in_signal.rate + .5;
p->delay_buf = lsx_calloc(p->delay_buf_len, sizeof(*p->delay_buf));
p->mod_buf_len = effp->in_signal.rate / p->mod_speed + .5;
p->mod_buf = lsx_malloc(p->mod_buf_len * sizeof(*p->mod_buf));
lsx_generate_wave_table(p->mod_type, SOX_INT, p->mod_buf, p->mod_buf_len,
1., (double)p->delay_buf_len, M_PI_2);
p->delay_pos = p->mod_pos = 0;
effp->out_signal.length = SOX_UNKNOWN_LEN; /* TODO: calculate actual length */
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);
while (len--) {
double d = *ibuf++ * p->in_gain + p->delay_buf[
(p->delay_pos + p->mod_buf[p->mod_pos]) % p->delay_buf_len] * p->decay;
p->mod_pos = (p->mod_pos + 1) % p->mod_buf_len;
p->delay_pos = (p->delay_pos + 1) % p->delay_buf_len;
p->delay_buf[p->delay_pos] = d;
*obuf++ = SOX_ROUND_CLIP_COUNT(d * p->out_gain, effp->clips);
}
return SOX_SUCCESS;
}
static int stop(sox_effect_t * effp)
{
priv_t * p = (priv_t *) effp->priv;
free(p->delay_buf);
free(p->mod_buf);
return SOX_SUCCESS;
}
sox_effect_handler_t const * lsx_phaser_effect_fn(void)
{
static sox_effect_handler_t handler = {
"phaser", "gain-in gain-out delay decay speed [ -s | -t ]",
SOX_EFF_LENGTH | SOX_EFF_GAIN, getopts, start, flow, NULL, stop, NULL, sizeof(priv_t)
};
return &handler;
}

@ -1,172 +0,0 @@
/* Pulse Audio sound handler
*
* Copyright 2008 Chris Bagwell And Sundry Contributors
*/
#include "sox_i.h"
#include <pulse/simple.h>
#include <pulse/error.h>
typedef struct {
pa_simple *pasp;
} priv_t;
static int setup(sox_format_t *ft, int is_input)
{
priv_t *pa = (priv_t *)ft->priv;
char *server;
pa_stream_direction_t dir;
char *app_str;
char *dev;
pa_sample_spec spec;
int error;
/* TODO: If user specified device of type "server:dev" then
* break up and override server.
*/
server = NULL;
if (is_input)
{
dir = PA_STREAM_RECORD;
app_str = "record";
}
else
{
dir = PA_STREAM_PLAYBACK;
app_str = "playback";
}
if (strncmp(ft->filename, "default", (size_t)7) == 0)
dev = NULL;
else
dev = ft->filename;
/* If user doesn't specify, default to some reasonable values.
* Since this is mainly for recording case, default to typical
* 16-bit values to prevent saving larger files then average user
* wants. Power users can override to 32-bit if they wish.
*/
if (ft->signal.channels == 0)
ft->signal.channels = 2;
if (ft->signal.rate == 0)
ft->signal.rate = 44100;
if (ft->encoding.bits_per_sample == 0)
{
ft->encoding.bits_per_sample = 16;
ft->encoding.encoding = SOX_ENCODING_SIGN2;
}
spec.format = PA_SAMPLE_S32NE;
spec.rate = ft->signal.rate;
spec.channels = ft->signal.channels;
pa->pasp = pa_simple_new(server, "SoX", dir, dev, app_str, &spec,
NULL, NULL, &error);
if (pa->pasp == NULL)
{
lsx_fail_errno(ft, SOX_EPERM, "can not open audio device: %s", pa_strerror(error));
return SOX_EOF;
}
/* TODO: Is it better to convert format/rates in SoX or in
* always let Pulse Audio do it? Since we don't know what
* hardware prefers, assume it knows best and give it
* what user specifies.
*/
return SOX_SUCCESS;
}
static int startread(sox_format_t *ft)
{
return setup(ft, 1);
}
static int stopread(sox_format_t * ft)
{
priv_t *pa = (priv_t *)ft->priv;
pa_simple_free(pa->pasp);
return SOX_SUCCESS;
}
static size_t read_samples(sox_format_t *ft, sox_sample_t *buf, size_t nsamp)
{
priv_t *pa = (priv_t *)ft->priv;
size_t len;
int rc, error;
/* Pulse Audio buffer lengths are true buffer lengths and not
* count of samples. */
len = nsamp * sizeof(sox_sample_t);
rc = pa_simple_read(pa->pasp, buf, len, &error);
if (rc < 0)
{
lsx_fail_errno(ft, SOX_EPERM, "error reading from pulse audio device: %s", pa_strerror(error));
return SOX_EOF;
}
else
return nsamp;
}
static int startwrite(sox_format_t * ft)
{
return setup(ft, 0);
}
static size_t write_samples(sox_format_t *ft, const sox_sample_t *buf, size_t nsamp)
{
priv_t *pa = (priv_t *)ft->priv;
size_t len;
int rc, error;
if (!nsamp)
return 0;
/* Pulse Audio buffer lengths are true buffer lengths and not
* count of samples. */
len = nsamp * sizeof(sox_sample_t);
rc = pa_simple_write(pa->pasp, buf, len, &error);
if (rc < 0)
{
lsx_fail_errno(ft, SOX_EPERM, "error writing to pulse audio device: %s", pa_strerror(error));
return SOX_EOF;
}
return nsamp;
}
static int stopwrite(sox_format_t * ft)
{
priv_t *pa = (priv_t *)ft->priv;
int error;
pa_simple_drain(pa->pasp, &error);
pa_simple_free(pa->pasp);
return SOX_SUCCESS;
}
LSX_FORMAT_HANDLER(pulseaudio)
{
static char const *const names[] = { "pulseaudio", NULL };
static unsigned const write_encodings[] = {
SOX_ENCODING_SIGN2, 32, 0,
0};
static sox_format_handler_t const handler = {SOX_LIB_VERSION_CODE,
"Pulse Audio client",
names, SOX_FILE_DEVICE | SOX_FILE_NOSTDIO,
startread, read_samples, stopread,
startwrite, write_samples, stopwrite,
NULL, write_encodings, NULL, sizeof(priv_t)
};
return &handler;
}

@ -1,30 +0,0 @@
/* libSoX file format: PVF 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"
LSX_FORMAT_HANDLER(pvf)
{
static char const * const names[] = {"pvf", NULL};
static unsigned const write_encodings[] = {SOX_ENCODING_SIGN2, 32, 16, 8,0,0};
static sox_format_handler_t handler;
handler = *lsx_sndfile_format_fn();
handler.description = "Portable Voice Format";
handler.names = names;
handler.write_formats = write_encodings;
return &handler;
}

@ -1,712 +0,0 @@
/* Effect: change sample rate Copyright (c) 2008,12 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
*/
/* Inspired by, and builds upon some of the ideas presented in:
* `The Quest For The Perfect Resampler' by Laurent De Soras;
* http://ldesoras.free.fr/doc/articles/resampler-en.pdf */
#ifdef NDEBUG /* Enable assert always. */
#undef NDEBUG /* Must undef above assert.h or other that might include it. */
#endif
#define _GNU_SOURCE
#include "sox_i.h"
#include "fft4g.h"
#include "dft_filter.h"
#include <assert.h>
#include <string.h>
#define calloc lsx_calloc
#define malloc lsx_malloc
#define raw_coef_t double
#if 0 /* For float32 version, as used in foobar */
#define sample_t float
#define num_coefs4 ((num_coefs + 3) & ~3) /* align coefs for SSE */
#define coefs4_check(i) ((i) < num_coefs)
#else
#define sample_t double
#define num_coefs4 num_coefs
#define coefs4_check(i) 1
#endif
#if defined M_PIl
#define hi_prec_clock_t long double /* __float128 is also a (slow) option */
#else
#define hi_prec_clock_t double
#endif
#define coef(coef_p, interp_order, fir_len, phase_num, coef_interp_num, fir_coef_num) coef_p[(fir_len) * ((interp_order) + 1) * (phase_num) + ((interp_order) + 1) * (fir_coef_num) + (interp_order - coef_interp_num)]
static sample_t * prepare_coefs(raw_coef_t const * coefs, int num_coefs,
int num_phases, int interp_order, int multiplier)
{
int i, j, length = num_coefs4 * num_phases;
sample_t * result = malloc(length * (interp_order + 1) * sizeof(*result));
double fm1 = coefs[0], f1 = 0, f2 = 0;
for (i = num_coefs4 - 1; i >= 0; --i)
for (j = num_phases - 1; j >= 0; --j) {
double f0 = fm1, b = 0, c = 0, d = 0; /* = 0 to kill compiler warning */
int pos = i * num_phases + j - 1;
fm1 = coefs4_check(i) && pos > 0 ? coefs[pos - 1] * multiplier : 0;
switch (interp_order) {
case 1: b = f1 - f0; break;
case 2: b = f1 - (.5 * (f2+f0) - f1) - f0; c = .5 * (f2+f0) - f1; break;
case 3: c=.5*(f1+fm1)-f0;d=(1/6.)*(f2-f1+fm1-f0-4*c);b=f1-f0-d-c; break;
default: if (interp_order) assert(0);
}
#define coef_coef(x) \
coef(result, interp_order, num_coefs4, j, x, num_coefs4 - 1 - i)
coef_coef(0) = f0;
if (interp_order > 0) coef_coef(1) = b;
if (interp_order > 1) coef_coef(2) = c;
if (interp_order > 2) coef_coef(3) = d;
#undef coef_coef
f2 = f1, f1 = f0;
}
return result;
}
typedef struct { /* So generated filter coefs may be shared between channels */
sample_t * poly_fir_coefs;
dft_filter_t dft_filter[2];
} rate_shared_t;
struct stage;
typedef void (* stage_fn_t)(struct stage * input, fifo_t * output);
typedef struct stage {
/* Common to all stage types: */
stage_fn_t fn;
fifo_t fifo;
int pre; /* Number of past samples to store */
int pre_post; /* pre + number of future samples to store */
int preload; /* Number of zero samples to pre-load the fifo */
double out_in_ratio; /* For buffer management. */
/* For a stage with variable (run-time generated) filter coefs: */
rate_shared_t * shared;
int dft_filter_num; /* Which, if any, of the 2 DFT filters to use */
/* For a stage with variable L/M: */
union { /* 32bit.32bit fixed point arithmetic */
#if defined(WORDS_BIGENDIAN)
struct {int32_t integer; uint32_t fraction;} parts;
#else
struct {uint32_t fraction; int32_t integer;} parts;
#endif
int64_t all;
#define MULT32 (65536. * 65536.)
hi_prec_clock_t hi_prec_clock;
} at, step;
sox_bool use_hi_prec_clock;
int L, remL, remM;
int n, phase_bits;
} stage_t;
#define stage_occupancy(s) max(0, fifo_occupancy(&(s)->fifo) - (s)->pre_post)
#define stage_read_p(s) ((sample_t *)fifo_read_ptr(&(s)->fifo) + (s)->pre)
static void cubic_stage_fn(stage_t * p, fifo_t * output_fifo)
{
int i, num_in = stage_occupancy(p), max_num_out = 1 + num_in*p->out_in_ratio;
sample_t const * input = stage_read_p(p);
sample_t * output = fifo_reserve(output_fifo, max_num_out);
for (i = 0; p->at.parts.integer < num_in; ++i, p->at.all += p->step.all) {
sample_t const * s = input + p->at.parts.integer;
sample_t x = p->at.parts.fraction * (1 / MULT32);
sample_t b = .5*(s[1]+s[-1])-*s, a = (1/6.)*(s[2]-s[1]+s[-1]-*s-4*b);
sample_t c = s[1]-*s-a-b;
output[i] = ((a*x + b)*x + c)*x + *s;
}
assert(max_num_out - i >= 0);
fifo_trim_by(output_fifo, max_num_out - i);
fifo_read(&p->fifo, p->at.parts.integer, NULL);
p->at.parts.integer = 0;
}
static void dft_stage_fn(stage_t * p, fifo_t * output_fifo)
{
sample_t * output, tmp;
int i, j, num_in = max(0, fifo_occupancy(&p->fifo));
rate_shared_t const * s = p->shared;
dft_filter_t const * f = &s->dft_filter[p->dft_filter_num];
int const overlap = f->num_taps - 1;
while (p->remL + p->L * num_in >= f->dft_length) {
div_t divd = div(f->dft_length - overlap - p->remL + p->L - 1, p->L);
sample_t const * input = fifo_read_ptr(&p->fifo);
fifo_read(&p->fifo, divd.quot, NULL);
num_in -= divd.quot;
output = fifo_reserve(output_fifo, f->dft_length);
if (lsx_is_power_of_2(p->L)) { /* F-domain */
int portion = f->dft_length / p->L;
memcpy(output, input, (unsigned)portion * sizeof(*output));
lsx_safe_rdft(portion, 1, output);
for (i = portion + 2; i < (portion << 1); i += 2)
output[i] = output[(portion << 1) - i],
output[i+1] = -output[(portion << 1) - i + 1];
output[portion] = output[1];
output[portion + 1] = 0;
output[1] = output[0];
for (portion <<= 1; i < f->dft_length; i += portion, portion <<= 1) {
memcpy(output + i, output, portion * sizeof(*output));
output[i + 1] = 0;
}
} else {
if (p->L == 1)
memcpy(output, input, f->dft_length * sizeof(*output));
else {
memset(output, 0, f->dft_length * sizeof(*output));
for (j = 0, i = p->remL; i < f->dft_length; ++j, i += p->L)
output[i] = input[j];
p->remL = p->L - 1 - divd.rem;
}
lsx_safe_rdft(f->dft_length, 1, output);
}
output[0] *= f->coefs[0];
if (p->step.parts.integer > 0) {
output[1] *= f->coefs[1];
for (i = 2; i < f->dft_length; i += 2) {
tmp = output[i];
output[i ] = f->coefs[i ] * tmp - f->coefs[i+1] * output[i+1];
output[i+1] = f->coefs[i+1] * tmp + f->coefs[i ] * output[i+1];
}
lsx_safe_rdft(f->dft_length, -1, output);
if (p->step.parts.integer != 1) {
for (j = 0, i = p->remM; i < f->dft_length - overlap; ++j,
i += p->step.parts.integer)
output[j] = output[i];
p->remM = i - (f->dft_length - overlap);
fifo_trim_by(output_fifo, f->dft_length - j);
}
else fifo_trim_by(output_fifo, overlap);
}
else { /* F-domain */
int m = -p->step.parts.integer;
for (i = 2; i < (f->dft_length >> m); i += 2) {
tmp = output[i];
output[i ] = f->coefs[i ] * tmp - f->coefs[i+1] * output[i+1];
output[i+1] = f->coefs[i+1] * tmp + f->coefs[i ] * output[i+1];
}
output[1] = f->coefs[i] * output[i] - f->coefs[i+1] * output[i+1];
lsx_safe_rdft(f->dft_length >> m, -1, output);
fifo_trim_by(output_fifo, (((1 << m) - 1) * f->dft_length + overlap) >>m);
}
}
}
static void dft_stage_init(
unsigned instance, double Fp, double Fs, double Fn, double att,
double phase, stage_t * stage, int L, int M)
{
dft_filter_t * f = &stage->shared->dft_filter[instance];
if (!f->num_taps) {
int num_taps = 0, dft_length, i;
int k = phase == 50 && lsx_is_power_of_2(L) && Fn == L? L << 1 : 4;
double * h = lsx_design_lpf(Fp, Fs, Fn, att, &num_taps, -k, -1.);
if (phase != 50)
lsx_fir_to_phase(&h, &num_taps, &f->post_peak, phase);
else f->post_peak = num_taps / 2;
dft_length = lsx_set_dft_length(num_taps);
f->coefs = calloc(dft_length, sizeof(*f->coefs));
for (i = 0; i < num_taps; ++i)
f->coefs[(i + dft_length - num_taps + 1) & (dft_length - 1)]
= h[i] / dft_length * 2 * L;
free(h);
f->num_taps = num_taps;
f->dft_length = dft_length;
lsx_safe_rdft(dft_length, 1, f->coefs);
lsx_debug("fir_len=%i dft_length=%i Fp=%g Fs=%g Fn=%g att=%g %i/%i",
num_taps, dft_length, Fp, Fs, Fn, att, L, M);
}
stage->fn = dft_stage_fn;
stage->preload = f->post_peak / L;
stage->remL = f->post_peak % L;
stage->L = L;
stage->step.parts.integer = abs(3-M) == 1 && Fs == 1? -M/2 : M;
stage->dft_filter_num = instance;
}
#include "rate_filters.h"
typedef struct {
double factor;
uint64_t samples_in, samples_out;
int num_stages;
stage_t * stages;
} rate_t;
#define pre_stage p->stages[shift]
#define arb_stage p->stages[shift + have_pre_stage]
#define post_stage p->stages[shift + have_pre_stage + have_arb_stage]
#define have_pre_stage (preM * preL != 1)
#define have_arb_stage (arbM * arbL != 1)
#define have_post_stage (postM * postL != 1)
#define TO_3dB(a) ((1.6e-6*a-7.5e-4)*a+.646)
#define LOW_Q_BW0_PC (67 + 5 / 8.)
typedef enum {
rolloff_none, rolloff_small /* <= 0.01 dB */, rolloff_medium /* <= 0.35 dB */
} rolloff_t;
static void rate_init(
/* Private work areas (to be supplied by the client): */
rate_t * p, /* Per audio channel. */
rate_shared_t * shared, /* Between channels (undergoing same rate change)*/
/* Public parameters: Typically */
double factor, /* Input rate divided by output rate. */
double bits, /* Required bit-accuracy (pass + stop) 16|20|28 */
double phase, /* Linear/minimum etc. filter phase. 50 */
double bw_pc, /* Pass-band % (0dB pt.) to preserve. 91.3|98.4*/
double anti_aliasing_pc, /* % bandwidth without aliasing 100 */
rolloff_t rolloff, /* Pass-band roll-off small */
sox_bool maintain_3dB_pt, /* true */
/* Primarily for test/development purposes: */
sox_bool use_hi_prec_clock,/* Increase irrational ratio accuracy. false */
int interpolator, /* Force a particular coef interpolator. -1 */
int max_coefs_size, /* k bytes of coefs to try to keep below. 400 */
sox_bool noSmallIntOpt) /* Disable small integer optimisations. false */
{
double att = (bits + 1) * linear_to_dB(2.), attArb = att; /* pass + stop */
double tbw0 = 1 - bw_pc / 100, Fs_a = 2 - anti_aliasing_pc / 100;
double arbM = factor, tbw_tighten = 1;
int n = 0, i, preL = 1, preM = 1, shift = 0, arbL = 1, postL = 1, postM = 1;
sox_bool upsample = sox_false, rational = sox_false, iOpt = !noSmallIntOpt;
int mode = rolloff > rolloff_small? factor > 1 || bw_pc > LOW_Q_BW0_PC :
ceil(2 + (bits - 17) / 4);
stage_t * s;
assert(factor > 0);
assert(!bits || (15 <= bits && bits <= 33));
assert(0 <= phase && phase <= 100);
assert(53 <= bw_pc && bw_pc <= 100);
assert(85 <= anti_aliasing_pc && anti_aliasing_pc <= 100);
p->factor = factor;
if (bits) while (!n++) { /* Determine stages: */
int try, L, M, x, maxL = interpolator > 0? 1 : mode? 2048 :
ceil(max_coefs_size * 1000. / (U100_l * sizeof(sample_t)));
double d, epsilon = 0, frac;
upsample = arbM < 1;
for (i = arbM * .5, shift = 0; i >>= 1; arbM *= .5, ++shift);
preM = upsample || (arbM > 1.5 && arbM < 2);
postM = 1 + (arbM > 1 && preM), arbM /= postM;
preL = 1 + (!preM && arbM < 2) + (upsample && mode), arbM *= preL;
if ((frac = arbM - (int)arbM))
epsilon = fabs((uint32_t)(frac * MULT32 + .5) / (frac * MULT32) - 1);
for (i = 1, rational = !frac; i <= maxL && !rational; ++i) {
d = frac * i, try = d + .5;
if ((rational = fabs(try / d - 1) <= epsilon)) { /* No long doubles! */
if (try == i)
arbM = ceil(arbM), shift += arbM > 2, arbM /= 1 + (arbM > 2);
else arbM = i * (int)arbM + try, arbL = i;
}
}
L = preL * arbL, M = arbM * postM, x = (L|M)&1, L >>= !x, M >>= !x;
if (iOpt && postL == 1 && (d = preL * arbL / arbM) > 4 && d != 5) {
for (postL = 4, i = d / 16; i >>= 1; postL <<= 1);
arbM = arbM * postL / arbL / preL, arbL = 1, n = 0;
} else if (rational && (max(L, M) < 3 + 2 * iOpt || L * M < 6 * iOpt))
preL = L, preM = M, arbM = arbL = postM = 1;
if (!mode && (!rational || !n))
++mode, n = 0;
}
p->num_stages = shift + have_pre_stage + have_arb_stage + have_post_stage;
if (!p->num_stages)
return;
p->stages = calloc(p->num_stages + 1, sizeof(*p->stages));
for (i = 0; i < p->num_stages; ++i)
p->stages[i].shared = shared;
if ((n = p->num_stages) > 1) { /* Att. budget: */
if (have_arb_stage)
att += linear_to_dB(2.), attArb = att, --n;
att += linear_to_dB((double)n);
}
for (n = 0; n + 1u < array_length(half_firs) && att > half_firs[n].att; ++n);
for (i = 0, s = p->stages; i < shift; ++i, ++s) {
s->fn = half_firs[n].fn;
s->pre_post = 4 * half_firs[n].num_coefs;
s->preload = s->pre = s->pre_post >> 1;
}
if (have_pre_stage) {
if (maintain_3dB_pt && have_post_stage) { /* Trans. bands overlapping. */
double tbw3 = tbw0 * TO_3dB(att); /* TODO: consider Fs_a. */
double x = ((2.1429e-4 - 5.2083e-7 * att) * att - .015863) * att + 3.95;
x = att * pow((tbw0 - tbw3) / (postM / (factor * postL) - 1 + tbw0), x);
if (x > .035) {
tbw_tighten = ((4.3074e-3 - 3.9121e-4 * x) * x - .040009) * x + 1.0014;
lsx_debug("x=%g tbw_tighten=%g", x, tbw_tighten);
}
}
dft_stage_init(0, 1 - tbw0 * tbw_tighten, Fs_a, preM? max(preL, preM) :
arbM / arbL, att, phase, &pre_stage, preL, max(preM, 1));
}
if (!bits) { /* Quick and dirty arb stage: */
arb_stage.fn = cubic_stage_fn;
arb_stage.step.all = arbM * MULT32 + .5;
arb_stage.pre_post = max(3, arb_stage.step.parts.integer);
arb_stage.preload = arb_stage.pre = 1;
arb_stage.out_in_ratio = MULT32 * arbL / arb_stage.step.all;
}
else if (have_arb_stage) { /* Higher quality arb stage: */
poly_fir_t const * f = &poly_firs[6*(upsample + !!preM) + mode - !upsample];
int order, num_coefs = f->interp[0].scalar, phase_bits, phases, coefs_size;
double x = .5, at, Fp, Fs, Fn, mult = upsample? 1 : arbL / arbM;
poly_fir1_t const * f1;
Fn = !upsample && preM? x = arbM / arbL : 1;
Fp = !preM? mult : mode? .5 : 1;
Fs = 2 - Fp; /* Ignore Fs_a; it would have little benefit here. */
Fp *= 1 - tbw0;
if (rolloff > rolloff_small && mode)
Fp = !preM? mult * .5 - .125 : mult * .05 + .1;
else if (rolloff == rolloff_small)
Fp = Fs - (Fs - .148 * x - Fp * .852) * (.00813 * bits + .973);
i = (interpolator < 0? !rational : max(interpolator, !rational)) - 1;
do {
f1 = &f->interp[++i];
assert(f1->fn);
if (i)
arbM /= arbL, arbL = 1, rational = sox_false;
phase_bits = ceil(f1->scalar + log(mult)/log(2.));
phases = !rational? (1 << phase_bits) : arbL;
if (!f->interp[0].scalar) {
int phases0 = max(phases, 19), n0 = 0;
lsx_design_lpf(Fp, Fs, -Fn, attArb, &n0, phases0, f->beta);
num_coefs = n0 / phases0 + 1, num_coefs += num_coefs & !preM;
}
if ((num_coefs & 1) && rational && (arbL & 1))
phases <<= 1, arbL <<= 1, arbM *= 2;
at = arbL * .5 * (num_coefs & 1);
order = i + (i && mode > 4);
coefs_size = num_coefs4 * phases * (order + 1) * sizeof(sample_t);
} while (interpolator < 0 && i < 2 && f->interp[i+1].fn &&
coefs_size / 1000 > max_coefs_size);
if (!arb_stage.shared->poly_fir_coefs) {
int num_taps = num_coefs * phases - 1;
raw_coef_t * coefs = lsx_design_lpf(
Fp, Fs, Fn, attArb, &num_taps, phases, f->beta);
arb_stage.shared->poly_fir_coefs = prepare_coefs(
coefs, num_coefs, phases, order, 1);
lsx_debug("fir_len=%i phases=%i coef_interp=%i size=%s",
num_coefs, phases, order, lsx_sigfigs3((double)coefs_size));
free(coefs);
}
arb_stage.fn = f1->fn;
arb_stage.pre_post = num_coefs4 - 1;
arb_stage.preload = (num_coefs - 1) >> 1;
arb_stage.n = num_coefs4;
arb_stage.phase_bits = phase_bits;
arb_stage.L = arbL;
arb_stage.use_hi_prec_clock = mode > 1 && use_hi_prec_clock && !rational;
if (arb_stage.use_hi_prec_clock) {
arb_stage.at.hi_prec_clock = at;
arb_stage.step.hi_prec_clock = arbM;
arb_stage.out_in_ratio = arbL / arb_stage.step.hi_prec_clock;
} else {
arb_stage.at.all = at * MULT32 + .5;
arb_stage.step.all = arbM * MULT32 + .5;
arb_stage.out_in_ratio = MULT32 * arbL / arb_stage.step.all;
}
}
if (have_post_stage)
dft_stage_init(1, 1 - (1 - (1 - tbw0) *
(upsample? factor * postL / postM : 1)) * tbw_tighten, Fs_a,
(double)max(postL, postM), att, phase, &post_stage, postL, postM);
for (i = 0, s = p->stages; i < p->num_stages; ++i, ++s) {
fifo_create(&s->fifo, (int)sizeof(sample_t));
memset(fifo_reserve(&s->fifo, s->preload), 0, sizeof(sample_t)*s->preload);
lsx_debug("%5i|%-5i preload=%i remL=%i",
s->pre, s->pre_post - s->pre, s->preload, s->remL);
}
fifo_create(&s->fifo, (int)sizeof(sample_t));
}
static void rate_process(rate_t * p)
{
stage_t * stage = p->stages;
int i;
for (i = 0; i < p->num_stages; ++i, ++stage)
stage->fn(stage, &(stage+1)->fifo);
}
static sample_t * rate_input(rate_t * p, sample_t const * samples, size_t n)
{
p->samples_in += n;
return fifo_write(&p->stages[0].fifo, (int)n, samples);
}
static sample_t const * rate_output(rate_t * p, sample_t * samples, size_t * n)
{
fifo_t * fifo = &p->stages[p->num_stages].fifo;
p->samples_out += *n = min(*n, (size_t)fifo_occupancy(fifo));
return fifo_read(fifo, (int)*n, samples);
}
static void rate_flush(rate_t * p)
{
fifo_t * fifo = &p->stages[p->num_stages].fifo;
uint64_t samples_out = p->samples_in / p->factor + .5;
size_t remaining = samples_out > p->samples_out ?
(size_t)(samples_out - p->samples_out) : 0;
sample_t * buff = calloc(1024, sizeof(*buff));
if (remaining > 0) {
while ((size_t)fifo_occupancy(fifo) < remaining) {
rate_input(p, buff, (size_t) 1024);
rate_process(p);
}
fifo_trim_to(fifo, (int)remaining);
p->samples_in = 0;
}
free(buff);
}
static void rate_close(rate_t * p)
{
rate_shared_t *shared;
int i;
if (!p->num_stages)
return;
shared = p->stages[0].shared;
for (i = 0; i <= p->num_stages; ++i)
fifo_delete(&p->stages[i].fifo);
free(shared->dft_filter[0].coefs);
free(shared->dft_filter[1].coefs);
free(shared->poly_fir_coefs);
memset(shared, 0, sizeof(*shared));
free(p->stages);
}
/*------------------------------- SoX Wrapper --------------------------------*/
typedef struct {
sox_rate_t out_rate;
int rolloff, coef_interp, max_coefs_size;
double bit_depth, phase, bw_0dB_pc, anti_aliasing_pc;
sox_bool use_hi_prec_clock, noIOpt, given_0dB_pt;
rate_t rate;
rate_shared_t shared, * shared_ptr;
} priv_t;
static int create(sox_effect_t * effp, int argc, char **argv)
{
priv_t * p = (priv_t *) effp->priv;
int c, quality;
char * dummy_p, * found_at;
char const * opts = "+i:c:b:B:A:p:Q:R:d:MILafnost" "qlmghevu";
char const * qopts = strchr(opts, 'q');
double rej = 0, bw_3dB_pc = 0;
sox_bool allow_aliasing = sox_false;
lsx_getopt_t optstate;
lsx_getopt_init(argc, argv, opts, NULL, lsx_getopt_flag_none, 1, &optstate);
p->coef_interp = quality = -1;
p->rolloff = rolloff_small;
p->phase = 50;
p->max_coefs_size = 400;
p->shared_ptr = &p->shared;
while ((c = lsx_getopt(&optstate)) != -1) switch (c) {
GETOPT_NUMERIC(optstate, 'i', coef_interp, -1, 2)
GETOPT_NUMERIC(optstate, 'c', max_coefs_size, 100, INT_MAX)
GETOPT_NUMERIC(optstate, 'p', phase, 0, 100)
GETOPT_NUMERIC(optstate, 'B', bw_0dB_pc, 53, 99.5)
GETOPT_NUMERIC(optstate, 'A', anti_aliasing_pc, 85, 100)
GETOPT_NUMERIC(optstate, 'd', bit_depth, 15, 33)
GETOPT_LOCAL_NUMERIC(optstate, 'b', bw_3dB_pc, 74, 99.7)
GETOPT_LOCAL_NUMERIC(optstate, 'R', rej, 90, 200)
GETOPT_LOCAL_NUMERIC(optstate, 'Q', quality, 0, 7)
case 'M': p->phase = 0; break;
case 'I': p->phase = 25; break;
case 'L': p->phase = 50; break;
case 'a': allow_aliasing = sox_true; break;
case 'f': p->rolloff = rolloff_none; break;
case 'n': p->noIOpt = sox_true; break;
case 's': bw_3dB_pc = 99; break;
case 't': p->use_hi_prec_clock = sox_true; break;
default:
if ((found_at = strchr(qopts, c)))
quality = found_at - qopts;
else {
lsx_fail("unknown option `-%c'", optstate.opt);
return lsx_usage(effp);
}
}
argc -= optstate.ind, argv += optstate.ind;
if ((unsigned)quality < 2 && (p->bw_0dB_pc || bw_3dB_pc || p->phase != 50 ||
allow_aliasing || rej || p->bit_depth || p->anti_aliasing_pc)) {
lsx_fail("override options not allowed with this quality level");
return SOX_EOF;
}
if (quality < 0 && rej == 0 && p->bit_depth == 0)
quality = 4;
if (rej)
p->bit_depth = rej / linear_to_dB(2.);
else {
if (quality >= 0) {
p->bit_depth = quality? 16 + 4 * max(quality - 3, 0) : 0;
if (quality <= 2)
p->rolloff = rolloff_medium;
}
rej = p->bit_depth * linear_to_dB(2.);
}
if (bw_3dB_pc && p->bw_0dB_pc) {
lsx_fail("conflicting bandwidth options");
return SOX_EOF;
}
allow_aliasing |= p->anti_aliasing_pc != 0;
if (!bw_3dB_pc && !p->bw_0dB_pc)
p->bw_0dB_pc = quality == 1? LOW_Q_BW0_PC : 100 - 5 / TO_3dB(rej);
else if (bw_3dB_pc && bw_3dB_pc < 85 && allow_aliasing) {
lsx_fail("minimum allowed 3dB bandwidth with aliasing is %g%%", 85.);
return SOX_EOF;
}
else if (p->bw_0dB_pc && p->bw_0dB_pc < 74 && allow_aliasing) {
lsx_fail("minimum allowed bandwidth with aliasing is %g%%", 74.);
return SOX_EOF;
}
if (bw_3dB_pc)
p->bw_0dB_pc = 100 - (100 - bw_3dB_pc) / TO_3dB(rej);
else {
bw_3dB_pc = 100 - (100 - p->bw_0dB_pc) * TO_3dB(rej);
p->given_0dB_pt = sox_true;
}
p->anti_aliasing_pc = p->anti_aliasing_pc? p->anti_aliasing_pc :
allow_aliasing? bw_3dB_pc : 100;
if (argc) {
if ((p->out_rate = lsx_parse_frequency(*argv, &dummy_p)) <= 0 || *dummy_p)
return lsx_usage(effp);
argc--; argv++;
effp->out_signal.rate = p->out_rate;
}
return argc? lsx_usage(effp) : SOX_SUCCESS;
}
static int start(sox_effect_t * effp)
{
priv_t * p = (priv_t *) effp->priv;
double out_rate = p->out_rate != 0 ? p->out_rate : effp->out_signal.rate;
if (effp->in_signal.rate == out_rate)
return SOX_EFF_NULL;
if (effp->in_signal.mult)
*effp->in_signal.mult *= .705; /* 1/(2/sinc(pi/3)-1); see De Soras 4.1.2 */
effp->out_signal.channels = effp->in_signal.channels;
effp->out_signal.rate = out_rate;
rate_init(&p->rate, p->shared_ptr, effp->in_signal.rate/out_rate,p->bit_depth,
p->phase, p->bw_0dB_pc, p->anti_aliasing_pc, p->rolloff, !p->given_0dB_pt,
p->use_hi_prec_clock, p->coef_interp, p->max_coefs_size, p->noIOpt);
if (!p->rate.num_stages) {
lsx_warn("input and output rates too close, skipping resampling");
return SOX_EFF_NULL;
}
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 odone = *osamp;
sample_t const * s = rate_output(&p->rate, NULL, &odone);
lsx_save_samples(obuf, s, odone, &effp->clips);
if (*isamp && odone < *osamp) {
sample_t * t = rate_input(&p->rate, NULL, *isamp);
lsx_load_samples(t, ibuf, *isamp);
rate_process(&p->rate);
}
else *isamp = 0;
*osamp = odone;
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;
rate_flush(&p->rate);
return flow(effp, 0, obuf, &isamp, osamp);
}
static int stop(sox_effect_t * effp)
{
priv_t * p = (priv_t *) effp->priv;
rate_close(&p->rate);
return SOX_SUCCESS;
}
sox_effect_handler_t const * lsx_rate_effect_fn(void)
{
static sox_effect_handler_t handler = {
"rate", 0, SOX_EFF_RATE, create, start, flow, drain, stop, 0, sizeof(priv_t)
};
static char const * lines[] = {
"[-q|-l|-m|-h|-v] [override-options] RATE[k]",
" BAND-",
" QUALITY WIDTH REJ dB TYPICAL USE",
" -q quick n/a ~30 @ Fs/4 playback on ancient hardware",
" -l low 80% 100 playback on old hardware",
" -m medium 95% 100 audio playback",
" -h high (default) 95% 125 16-bit mastering (use with dither)",
" -v very high 95% 175 24-bit mastering",
" OVERRIDE OPTIONS (only with -m, -h, -v)",
" -M/-I/-L Phase response = minimum/intermediate/linear(default)",
" -s Steep filter (band-width = 99%)",
" -a Allow aliasing above the pass-band",
" -b 74-99.7 Any band-width %",
" -p 0-100 Any phase response (0 = minimum, 25 = intermediate,",
" 50 = linear, 100 = maximum)",
};
static char * usage;
handler.usage = lsx_usage_lines(&usage, lines, array_length(lines));
return &handler;
}

@ -1,187 +0,0 @@
/* Effect: change sample rate Copyright (c) 2008,12 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
*/
static const sample_t half_fir_coefs_8[] = {
0.3115465451887802, -0.08734497241282892, 0.03681452335604365,
-0.01518925831569441, 0.005454118437408876, -0.001564400922162005,
0.0003181701445034203, -3.48001341225749e-5,
};
#define FUNCTION h8
#define CONVOLVE _ _ _ _ _ _ _ _
#define h8_l 8
#define COEFS half_fir_coefs_8
#include "rate_half_fir.h"
static const sample_t half_fir_coefs_9[] = {
0.3122703613711853, -0.08922155288172305, 0.03913974805854332,
-0.01725059723447163, 0.006858970092378141, -0.002304518467568703,
0.0006096426006051062, -0.0001132393923815236, 1.119795386287666e-5,
};
#define FUNCTION h9
#define CONVOLVE _ _ _ _ _ _ _ _ _
#define h9_l 9
#define COEFS half_fir_coefs_9
#include "rate_half_fir.h"
static const sample_t half_fir_coefs_10[] = {
0.3128545521327376, -0.09075671986104322, 0.04109637155154835,
-0.01906629512749895, 0.008184039342054333, -0.0030766775017262,
0.0009639607022414314, -0.0002358552746579827, 4.025184282444155e-5,
-3.629779111541012e-6,
};
#define FUNCTION h10
#define CONVOLVE _ _ _ _ _ _ _ _ _ _
#define h10_l 10
#define COEFS half_fir_coefs_10
#include "rate_half_fir.h"
static const sample_t half_fir_coefs_11[] = {
0.3133358837508807, -0.09203588680609488, 0.04276515428384758,
-0.02067356614745591, 0.00942253142371517, -0.003856330993895144,
0.001363470684892284, -0.0003987400965541919, 9.058629923971627e-5,
-1.428553070915318e-5, 1.183455238783835e-6,
};
#define FUNCTION h11
#define CONVOLVE _ _ _ _ _ _ _ _ _ _ _
#define h11_l 11
#define COEFS half_fir_coefs_11
#include "rate_half_fir.h"
static const sample_t half_fir_coefs_12[] = {
0.3137392991811407, -0.0931182192961332, 0.0442050575271454,
-0.02210391200618091, 0.01057473015666001, -0.00462766983973885,
0.001793630226239453, -0.0005961819959665878, 0.0001631475979359577,
-3.45557865639653e-5, 5.06188341942088e-6, -3.877010943315563e-7,
};
#define FUNCTION h12
#define CONVOLVE _ _ _ _ _ _ _ _ _ _ _ _
#define h12_l 12
#define COEFS half_fir_coefs_12
#include "rate_half_fir.h"
static const sample_t half_fir_coefs_13[] = {
0.3140822554324578, -0.0940458550886253, 0.04545990399121566,
-0.02338339450796002, 0.01164429409071052, -0.005380686021429845,
0.002242915773871009, -0.000822047600000082, 0.0002572510962395222,
-6.607320708956279e-5, 1.309926399120154e-5, -1.790719575255006e-6,
1.27504961098836e-7,
};
#define FUNCTION h13
#define CONVOLVE _ _ _ _ _ _ _ _ _ _ _ _ _
#define h13_l 13
#define COEFS half_fir_coefs_13
#include "rate_half_fir.h"
static struct {int num_coefs; stage_fn_t fn; float att;} const half_firs[] = {
{ 8, h8 , 136.51},
{ 9, h9 , 152.32},
{10, h10, 168.07},
{11, h11, 183.78},
{12, h12, 199.44},
{13, h13, 212.75},
};
#define HI_PREC_CLOCK
#define VAR_LENGTH p->n
#define VAR_CONVOLVE while (j < FIR_LENGTH) _
#define VAR_POLY_PHASE_BITS p->phase_bits
#define FUNCTION vpoly0
#define FIR_LENGTH VAR_LENGTH
#define CONVOLVE VAR_CONVOLVE
#include "rate_poly_fir0.h"
#define FUNCTION vpoly1
#define COEF_INTERP 1
#define PHASE_BITS VAR_POLY_PHASE_BITS
#define FIR_LENGTH VAR_LENGTH
#define CONVOLVE VAR_CONVOLVE
#include "rate_poly_fir.h"
#define FUNCTION vpoly2
#define COEF_INTERP 2
#define PHASE_BITS VAR_POLY_PHASE_BITS
#define FIR_LENGTH VAR_LENGTH
#define CONVOLVE VAR_CONVOLVE
#include "rate_poly_fir.h"
#define FUNCTION vpoly3
#define COEF_INTERP 3
#define PHASE_BITS VAR_POLY_PHASE_BITS
#define FIR_LENGTH VAR_LENGTH
#define CONVOLVE VAR_CONVOLVE
#include "rate_poly_fir.h"
#undef HI_PREC_CLOCK
#define U100_l 42
#define poly_fir_convolve_U100 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
#define FUNCTION U100_0
#define FIR_LENGTH U100_l
#define CONVOLVE poly_fir_convolve_U100
#include "rate_poly_fir0.h"
#define u100_l 11
#define poly_fir_convolve_u100 _ _ _ _ _ _ _ _ _ _ _
#define FUNCTION u100_0
#define FIR_LENGTH u100_l
#define CONVOLVE poly_fir_convolve_u100
#include "rate_poly_fir0.h"
#define FUNCTION u100_1
#define COEF_INTERP 1
#define PHASE_BITS 8
#define FIR_LENGTH u100_l
#define CONVOLVE poly_fir_convolve_u100
#include "rate_poly_fir.h"
#define u100_1_b 8
#define FUNCTION u100_2
#define COEF_INTERP 2
#define PHASE_BITS 6
#define FIR_LENGTH u100_l
#define CONVOLVE poly_fir_convolve_u100
#include "rate_poly_fir.h"
#define u100_2_b 6
typedef struct {float scalar; stage_fn_t fn;} poly_fir1_t;
typedef struct {float beta; poly_fir1_t interp[3];} poly_fir_t;
static poly_fir_t const poly_firs[] = {
{-1, {{0, vpoly0}, { 7.2, vpoly1}, {5.0, vpoly2}}},
{-1, {{0, vpoly0}, { 9.4, vpoly1}, {6.7, vpoly2}}},
{-1, {{0, vpoly0}, {12.4, vpoly1}, {7.8, vpoly2}}},
{-1, {{0, vpoly0}, {13.6, vpoly1}, {9.3, vpoly2}}},
{-1, {{0, vpoly0}, {10.5, vpoly2}, {8.4, vpoly3}}},
{-1, {{0, vpoly0}, {11.85,vpoly2}, {9.0, vpoly3}}},
{-1, {{0, vpoly0}, { 8.0, vpoly1}, {5.3, vpoly2}}},
{-1, {{0, vpoly0}, { 8.6, vpoly1}, {5.7, vpoly2}}},
{-1, {{0, vpoly0}, {10.6, vpoly1}, {6.75,vpoly2}}},
{-1, {{0, vpoly0}, {12.6, vpoly1}, {8.6, vpoly2}}},
{-1, {{0, vpoly0}, { 9.6, vpoly2}, {7.6, vpoly3}}},
{-1, {{0, vpoly0}, {11.4, vpoly2}, {8.65,vpoly3}}},
{10.62, {{U100_l, U100_0}, {0, 0}, {0, 0}}},
{11.28, {{u100_l, u100_0}, {u100_1_b, u100_1}, {u100_2_b, u100_2}}},
{-1, {{0, vpoly0}, { 9, vpoly1}, { 6, vpoly2}}},
{-1, {{0, vpoly0}, { 11, vpoly1}, { 7, vpoly2}}},
{-1, {{0, vpoly0}, { 13, vpoly1}, { 8, vpoly2}}},
{-1, {{0, vpoly0}, { 10, vpoly2}, { 8, vpoly3}}},
{-1, {{0, vpoly0}, { 12, vpoly2}, { 9, vpoly3}}},
};

@ -1,39 +0,0 @@
/* Effect: change sample rate Copyright (c) 2008,12 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
*/
/* Down-sample by a factor of 2 using a FIR with odd length (LEN).*/
/* Input must be preceded and followed by LEN >> 1 samples. */
#define _ sum += (input[-(2*j +1)] + input[(2*j +1)]) * COEFS[j], ++j;
static void FUNCTION(stage_t * p, fifo_t * output_fifo)
{
sample_t const * input = stage_read_p(p);
int i, num_out = (stage_occupancy(p) + 1) / 2;
sample_t * output = fifo_reserve(output_fifo, num_out);
for (i = 0; i < num_out; ++i, input += 2) {
int j = 0;
sample_t sum = input[0] * .5;
CONVOLVE
output[i] = sum;
}
fifo_read(&p->fifo, 2 * num_out, NULL);
}
#undef _
#undef COEFS
#undef CONVOLVE
#undef FUNCTION

@ -1,91 +0,0 @@
/* Effect: change sample rate Copyright (c) 2008,12 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
*/
/* Resample using an interpolated poly-phase FIR with length LEN.*/
/* Input must be followed by LEN-1 samples. */
#define a (coef(p->shared->poly_fir_coefs, COEF_INTERP, FIR_LENGTH, phase, 0,j))
#define b (coef(p->shared->poly_fir_coefs, COEF_INTERP, FIR_LENGTH, phase, 1,j))
#define c (coef(p->shared->poly_fir_coefs, COEF_INTERP, FIR_LENGTH, phase, 2,j))
#define d (coef(p->shared->poly_fir_coefs, COEF_INTERP, FIR_LENGTH, phase, 3,j))
#if COEF_INTERP == 0
#define _ sum += a *in[j], ++j;
#elif COEF_INTERP == 1
#define _ sum += (b *x + a)*in[j], ++j;
#elif COEF_INTERP == 2
#define _ sum += ((c *x + b)*x + a)*in[j], ++j;
#elif COEF_INTERP == 3
#define _ sum += (((d*x + c)*x + b)*x + a)*in[j], ++j;
#else
#error COEF_INTERP
#endif
static void FUNCTION(stage_t * p, fifo_t * output_fifo)
{
sample_t const * input = stage_read_p(p);
int i, num_in = stage_occupancy(p), max_num_out = 1 + num_in*p->out_in_ratio;
sample_t * output = fifo_reserve(output_fifo, max_num_out);
#if defined HI_PREC_CLOCK
if (p->use_hi_prec_clock) {
hi_prec_clock_t at = p->at.hi_prec_clock;
for (i = 0; (int)at < num_in; ++i, at += p->step.hi_prec_clock) {
sample_t const * in = input + (int)at;
hi_prec_clock_t fraction = at - (int)at;
int phase = fraction * (1 << PHASE_BITS);
#if COEF_INTERP > 0
sample_t x = fraction * (1 << PHASE_BITS) - phase;
#endif
sample_t sum = 0;
int j = 0;
CONVOLVE
output[i] = sum;
}
fifo_read(&p->fifo, (int)at, NULL);
p->at.hi_prec_clock = at - (int)at;
} else
#endif
{
for (i = 0; p->at.parts.integer < num_in; ++i, p->at.all += p->step.all) {
sample_t const * in = input + p->at.parts.integer;
uint32_t fraction = p->at.parts.fraction;
int phase = fraction >> (32 - PHASE_BITS); /* high-order bits */
#if COEF_INTERP > 0 /* low-order bits, scaled to [0,1) */
sample_t x = (sample_t) (fraction << PHASE_BITS) * (1 / MULT32);
#endif
sample_t sum = 0;
int j = 0;
CONVOLVE
output[i] = sum;
}
fifo_read(&p->fifo, p->at.parts.integer, NULL);
p->at.parts.integer = 0;
}
assert(max_num_out - i >= 0);
fifo_trim_by(output_fifo, max_num_out - i);
}
#undef _
#undef a
#undef b
#undef c
#undef d
#undef COEF_INTERP
#undef CONVOLVE
#undef FIR_LENGTH
#undef FUNCTION
#undef PHASE_BITS

@ -1,48 +0,0 @@
/* Effect: change sample rate Copyright (c) 2008,12 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
*/
/* Resample using a non-interpolated poly-phase FIR with length LEN.*/
/* Input must be followed by LEN-1 samples. */
#define _ sum += (coef(p->shared->poly_fir_coefs, 0, FIR_LENGTH, divided.rem, 0, j)) *at[j], ++j;
static void FUNCTION(stage_t * p, fifo_t * output_fifo)
{
sample_t const * input = stage_read_p(p);
int i, num_in = stage_occupancy(p), max_num_out = 1 + num_in*p->out_in_ratio;
sample_t * output = fifo_reserve(output_fifo, max_num_out);
div_t divided2;
for (i = 0; p->at.parts.integer < num_in * p->L; ++i, p->at.parts.integer += p->step.parts.integer) {
div_t divided = div(p->at.parts.integer, p->L);
sample_t const * at = input + divided.quot;
sample_t sum = 0;
int j = 0;
CONVOLVE
output[i] = sum;
}
assert(max_num_out - i >= 0);
fifo_trim_by(output_fifo, max_num_out - i);
divided2 = div(p->at.parts.integer, p->L);
fifo_read(&p->fifo, divided2.quot, NULL);
p->at.parts.integer = divided2.rem;
}
#undef _
#undef CONVOLVE
#undef FIR_LENGTH
#undef FUNCTION

@ -1,61 +0,0 @@
/* libSoX file formats: raw (c) 2007-11 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"
static int raw_start(sox_format_t * ft) {
return lsx_rawstart(ft, sox_false, sox_false, sox_true, SOX_ENCODING_UNKNOWN, 0);
}
LSX_FORMAT_HANDLER(raw)
{
static char const * const names[] = {"raw", NULL};
static unsigned const encodings[] = {
SOX_ENCODING_SIGN2, 32, 24, 16, 8, 0,
SOX_ENCODING_UNSIGNED, 32, 24, 16, 8, 0,
SOX_ENCODING_ULAW, 8, 0,
SOX_ENCODING_ALAW, 8, 0,
SOX_ENCODING_FLOAT, 64, 32, 0,
0};
static sox_format_handler_t const handler = {SOX_LIB_VERSION_CODE,
"Raw PCM, mu-law, or A-law", names, 0,
raw_start, lsx_rawread , NULL,
raw_start, lsx_rawwrite, NULL,
lsx_rawseek, encodings, NULL, 0
};
return &handler;
}
static int sln_start(sox_format_t * ft)
{
return lsx_check_read_params(ft, 1, 8000., SOX_ENCODING_SIGN2, 16, (uint64_t)0, sox_false);
}
LSX_FORMAT_HANDLER(sln)
{
static char const * const names[] = {"sln", NULL};
static unsigned const write_encodings[] = {SOX_ENCODING_SIGN2, 16, 0, 0};
static sox_rate_t const write_rates[] = {8000, 0};
static sox_format_handler_t handler = {SOX_LIB_VERSION_CODE,
"Asterisk PBX headerless format",
names, SOX_FILE_LIT_END|SOX_FILE_MONO,
sln_start, lsx_rawread, NULL,
NULL, lsx_rawwrite, NULL,
lsx_rawseek, write_encodings, write_rates, 0
};
return &handler;
}

@ -1,284 +0,0 @@
/* libSoX effect: remix Copyright (c) 2008-9 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 {
enum {semi, automatic, manual} mode;
sox_bool mix_power;
unsigned num_out_channels, min_in_channels;
struct {
char * str; /* Command-line argument to parse for this out_spec */
unsigned num_in_channels;
struct in_spec {
unsigned channel_num;
double multiplier;
} * in_specs;
} * out_specs;
} priv_t;
#define PARSE(SEP, SCAN, VAR, MIN, SEPARATORS) do {\
end = strpbrk(text, SEPARATORS); \
if (end == text) \
SEP = *text++; \
else { \
SEP = (SEPARATORS)[strlen(SEPARATORS) - 1]; \
n = sscanf(text, SCAN"%c", &VAR, &SEP); \
if (n == 0 || VAR < MIN || (n == 2 && !strchr(SEPARATORS, SEP))) \
return lsx_usage(effp); \
text = end? end + 1 : text + strlen(text); \
} \
} while (0)
static int parse(sox_effect_t * effp, char * * argv, unsigned channels)
{
priv_t * p = (priv_t *)effp->priv;
unsigned i, j;
double mult;
p->min_in_channels = 0;
for (i = 0; i < p->num_out_channels; ++i) {
sox_bool mul_spec = sox_false;
char * text, * end;
if (argv) /* 1st parse only */
p->out_specs[i].str = lsx_strdup(argv[i]);
for (j = 0, text = p->out_specs[i].str; *text;) {
static char const separators[] = "-vpi,";
char sep1, sep2;
int chan1 = 1, chan2 = channels, n;
double multiplier = HUGE_VAL;
PARSE(sep1, "%i", chan1, 0, separators);
if (!chan1) {
if (j || *text)
return lsx_usage(effp);
continue;
}
if (sep1 == '-')
PARSE(sep1, "%i", chan2, 0, separators + 1);
else chan2 = chan1;
if (sep1 != ',') {
multiplier = sep1 == 'v' ? 1 : 0;
PARSE(sep2, "%lf", multiplier, -HUGE_VAL, separators + 4);
if (sep1 != 'v')
multiplier = (sep1 == 'p'? 1 : -1) * dB_to_linear(multiplier);
mul_spec = sox_true;
}
if (chan2 < chan1) {int t = chan1; chan1 = chan2; chan2 = t;}
p->out_specs[i].in_specs = lsx_realloc(p->out_specs[i].in_specs,
(j + chan2 - chan1 + 1) * sizeof(*p->out_specs[i].in_specs));
while (chan1 <= chan2) {
p->out_specs[i].in_specs[j].channel_num = chan1++ - 1;
p->out_specs[i].in_specs[j++].multiplier = multiplier;
}
p->min_in_channels = max(p->min_in_channels, (unsigned)chan2);
}
p->out_specs[i].num_in_channels = j;
mult = 1. / (p->mix_power? sqrt((double)j) : j);
for (j = 0; j < p->out_specs[i].num_in_channels; ++j)
if (p->out_specs[i].in_specs[j].multiplier == HUGE_VAL)
p->out_specs[i].in_specs[j].multiplier = (p->mode == automatic || (p->mode == semi && !mul_spec)) ? mult : 1;
}
effp->out_signal.channels = p->num_out_channels;
return SOX_SUCCESS;
}
static int show(priv_t *p)
{
unsigned i, j;
for (j = 0; j < p->num_out_channels; j++) {
lsx_debug("%i: ", j);
for (i = 0; i < p->out_specs[j].num_in_channels; i++)
lsx_debug("\t%i %g", p->out_specs[j].in_specs[i].channel_num, p->out_specs[j].in_specs[i].multiplier);
}
return SOX_SUCCESS;
}
static int create(sox_effect_t * effp, int argc, char * * argv)
{
priv_t * p = (priv_t *)effp->priv;
--argc, ++argv;
if (argc && !strcmp(*argv, "-m")) p->mode = manual , ++argv, --argc;
if (argc && !strcmp(*argv, "-a")) p->mode = automatic, ++argv, --argc;
if (argc && !strcmp(*argv, "-p")) p->mix_power = sox_true, ++argv, --argc;
if (!argc) {
lsx_fail("must specify at least one output channel");
return SOX_EOF;
}
p->num_out_channels = argc;
p->out_specs = lsx_calloc(p->num_out_channels, sizeof(*p->out_specs));
return parse(effp, argv, 1); /* No channels yet; parse with dummy */
}
static int start(sox_effect_t * effp)
{
priv_t * p = (priv_t *)effp->priv;
double max_sum = 0;
unsigned i, j;
int non_integer = 0;
parse(effp, NULL, effp->in_signal.channels);
if (effp->in_signal.channels < p->min_in_channels) {
lsx_fail("too few input channels");
return SOX_EOF;
}
for (j = 0; j < effp->out_signal.channels; j++) {
double sum = 0;
for (i = 0; i < p->out_specs[j].num_in_channels; i++) {
double mult = p->out_specs[j].in_specs[i].multiplier;
sum += fabs(mult);
non_integer += floor(mult) != mult;
}
max_sum = max(max_sum, sum);
}
if (effp->in_signal.mult && max_sum > 1)
*effp->in_signal.mult /= max_sum;
if (!non_integer)
effp->out_signal.precision = effp->in_signal.precision;
else
effp->out_signal.precision = SOX_SAMPLE_PRECISION;
show(p);
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;
unsigned i, j, len;
len = min(*isamp / effp->in_signal.channels, *osamp / effp->out_signal.channels);
*isamp = len * effp->in_signal.channels;
*osamp = len * effp->out_signal.channels;
for (; len--; ibuf += effp->in_signal.channels) for (j = 0; j < effp->out_signal.channels; j++) {
double out = 0;
for (i = 0; i < p->out_specs[j].num_in_channels; i++)
out += ibuf[p->out_specs[j].in_specs[i].channel_num] * p->out_specs[j].in_specs[i].multiplier;
*obuf++ = SOX_ROUND_CLIP_COUNT(out, effp->clips);
}
return SOX_SUCCESS;
}
static int closedown(sox_effect_t * effp)
{
priv_t * p = (priv_t *)effp->priv;
unsigned i;
for (i = 0; i < p->num_out_channels; ++i) {
free(p->out_specs[i].str);
free(p->out_specs[i].in_specs);
}
free(p->out_specs);
return SOX_SUCCESS;
}
sox_effect_handler_t const * lsx_remix_effect_fn(void)
{
static sox_effect_handler_t handler = {
"remix", "[-m|-a] [-p] <0|in-chan[v|p|i volume]{,in-chan[v|p|i volume]}>",
SOX_EFF_MCHAN | SOX_EFF_CHAN | SOX_EFF_GAIN | SOX_EFF_PREC,
create, start, flow, NULL, NULL, closedown, sizeof(priv_t)
};
return &handler;
}
/*----------------------- The `channels' effect alias ------------------------*/
static int channels_create(sox_effect_t * effp, int argc, char * * argv)
{
priv_t * p = (priv_t *)effp->priv;
char dummy; /* To check for extraneous chars. */
if (argc == 2) {
if (sscanf(argv[1], "%d %c", (int *)&p->num_out_channels,
&dummy) != 1 || (int)p->num_out_channels <= 0)
return lsx_usage(effp);
effp->out_signal.channels = p->num_out_channels;
}
else if (argc != 1)
return lsx_usage(effp);
return SOX_SUCCESS;
}
static int channels_start(sox_effect_t * effp)
{
priv_t * p = (priv_t *)effp->priv;
unsigned num_out_channels = p->num_out_channels != 0 ?
p->num_out_channels : effp->out_signal.channels;
unsigned i, j;
p->out_specs = lsx_calloc(num_out_channels, sizeof(*p->out_specs));
if (effp->in_signal.channels == num_out_channels)
return SOX_EFF_NULL;
if (effp->in_signal.channels > num_out_channels) {
for (j = 0; j < num_out_channels; j++) {
unsigned in_per_out = (effp->in_signal.channels +
num_out_channels - 1 - j) / num_out_channels;
lsx_valloc(p->out_specs[j].in_specs, in_per_out);
p->out_specs[j].num_in_channels = in_per_out;
for (i = 0; i < in_per_out; ++i) {
p->out_specs[j].in_specs[i].channel_num = i * num_out_channels + j;
p->out_specs[j].in_specs[i].multiplier = 1. / in_per_out;
}
}
}
else for (j = 0; j < num_out_channels; j++) {
lsx_valloc(p->out_specs[j].in_specs, 1);
p->out_specs[j].num_in_channels = 1;
p->out_specs[j].in_specs[0].channel_num = j % effp->in_signal.channels;
p->out_specs[j].in_specs[0].multiplier = 1;
}
effp->out_signal.channels = p->num_out_channels = num_out_channels;
effp->out_signal.precision = (effp->in_signal.channels > num_out_channels) ?
SOX_SAMPLE_PRECISION : effp->in_signal.precision;
show(p);
return SOX_SUCCESS;
}
sox_effect_handler_t const * lsx_channels_effect_fn(void)
{
static sox_effect_handler_t handler;
handler = *lsx_remix_effect_fn();
handler.name = "channels";
handler.usage = "number";
handler.flags &= ~SOX_EFF_GAIN;
handler.getopts = channels_create;
handler.start = channels_start;
return &handler;
}
/*------------------------- The `oops' effect alias --------------------------*/
static int oops_getopts(sox_effect_t *effp, int argc, char **argv)
{
char *args[] = {0, "1,2i", "1,2i"};
args[0] = argv[0];
return --argc? lsx_usage(effp) : create(effp, 3, args);
}
sox_effect_handler_t const * lsx_oops_effect_fn(void)
{
static sox_effect_handler_t handler;
handler = *lsx_remix_effect_fn();
handler.name = "oops";
handler.usage = NULL;
handler.getopts = oops_getopts;
return &handler;
}

@ -1,114 +0,0 @@
/* libSoX repeat effect Copyright (c) 2004 Jan Paul Schmidt <jps@fundament.org>
* Re-write (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 {
unsigned num_repeats, remaining_repeats;
uint64_t num_samples, remaining_samples;
FILE * tmp_file;
} priv_t;
static int create(sox_effect_t * effp, int argc, char * * argv)
{
priv_t * p = (priv_t *)effp->priv;
p->num_repeats = 1;
--argc, ++argv;
if (argc == 1 && !strcmp(*argv, "-")) {
p->num_repeats = UINT_MAX;
return SOX_SUCCESS;
}
do {NUMERIC_PARAMETER(num_repeats, 0, UINT_MAX - 1)} while (0);
return argc? lsx_usage(effp) : SOX_SUCCESS;
}
static int start(sox_effect_t * effp)
{
priv_t * p = (priv_t *)effp->priv;
if (!p->num_repeats)
return SOX_EFF_NULL;
if (!(p->tmp_file = lsx_tmpfile())) {
lsx_fail("can't create temporary file: %s", strerror(errno));
return SOX_EOF;
}
p->num_samples = p->remaining_samples = 0;
p->remaining_repeats = p->num_repeats;
if (effp->in_signal.length != SOX_UNKNOWN_LEN && p->num_repeats != UINT_MAX)
effp->out_signal.length = effp->in_signal.length * (p->num_repeats + 1);
else
effp->out_signal.length = SOX_UNKNOWN_LEN;
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 = min(*isamp, *osamp);
memcpy(obuf, ibuf, len * sizeof(*obuf));
if (fwrite(ibuf, sizeof(*ibuf), len, p->tmp_file) != len) {
lsx_fail("error writing temporary file: %s", strerror(errno));
return SOX_EOF;
}
p->num_samples += len;
*isamp = *osamp = len;
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 odone = 0, n;
*osamp -= *osamp % effp->in_signal.channels;
while ((p->remaining_samples || p->remaining_repeats) && odone < *osamp) {
if (!p->remaining_samples) {
p->remaining_samples = p->num_samples;
if (p->remaining_repeats != UINT_MAX)
--p->remaining_repeats;
rewind(p->tmp_file);
}
n = min(p->remaining_samples, *osamp - odone);
if ((fread(obuf + odone, sizeof(*obuf), n, p->tmp_file)) != n) {
lsx_fail("error reading temporary file: %s", strerror(errno));
return SOX_EOF;
}
p->remaining_samples -= n;
odone += n;
}
*osamp = odone;
return p->remaining_samples || p->remaining_repeats? SOX_SUCCESS : SOX_EOF;
}
static int stop(sox_effect_t * effp)
{
priv_t * p = (priv_t *)effp->priv;
fclose(p->tmp_file); /* auto-deleted by lsx_tmpfile */
return SOX_SUCCESS;
}
sox_effect_handler_t const * lsx_repeat_effect_fn(void)
{
static sox_effect_handler_t effect = {"repeat", "[count (1)]",
SOX_EFF_MCHAN | SOX_EFF_LENGTH | SOX_EFF_MODIFY,
create, start, flow, drain, stop, NULL, sizeof(priv_t)};
return &effect;
}

@ -1,86 +0,0 @@
/* June 1, 1992
* Copyright 1992 Guido van Rossum And Sundry Contributors
* This source code is freely redistributable and may be used for
* any purpose. This copyright notice must be maintained.
* Guido van Rossum And Sundry Contributors are not responsible for
* the consequences of using this software.
*/
/*
* "reverse" effect, uses a temporary file created by lsx_tmpfile().
*/
#include "sox_i.h"
#include <string.h>
typedef struct {
off_t pos;
FILE * tmp_file;
} priv_t;
static int start(sox_effect_t * effp)
{
priv_t * p = (priv_t *)effp->priv;
p->pos = 0;
p->tmp_file = lsx_tmpfile();
if (p->tmp_file == NULL) {
lsx_fail("can't create temporary file: %s", strerror(errno));
return SOX_EOF;
}
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;
if (fwrite(ibuf, sizeof(*ibuf), *isamp, p->tmp_file) != *isamp) {
lsx_fail("error writing temporary file: %s", strerror(errno));
return SOX_EOF;
}
(void)obuf, *osamp = 0; /* samples not output until drain */
return SOX_SUCCESS;
}
static int drain(sox_effect_t * effp, sox_sample_t *obuf, size_t *osamp)
{
priv_t * p = (priv_t *)effp->priv;
int i, j;
if (p->pos == 0) {
fflush(p->tmp_file);
p->pos = ftello(p->tmp_file);
if (p->pos % sizeof(sox_sample_t) != 0) {
lsx_fail("temporary file has incorrect size");
return SOX_EOF;
}
p->pos /= sizeof(sox_sample_t);
}
p->pos -= *osamp = min((off_t)*osamp, p->pos);
fseeko(p->tmp_file, (off_t)(p->pos * sizeof(sox_sample_t)), SEEK_SET);
if (fread(obuf, sizeof(sox_sample_t), *osamp, p->tmp_file) != *osamp) {
lsx_fail("error reading temporary file: %s", strerror(errno));
return SOX_EOF;
}
for (i = 0, j = *osamp - 1; i < j; ++i, --j) { /* reverse the samples */
sox_sample_t temp = obuf[i];
obuf[i] = obuf[j];
obuf[j] = temp;
}
return p->pos? SOX_SUCCESS : SOX_EOF;
}
static int stop(sox_effect_t * effp)
{
priv_t * p = (priv_t *)effp->priv;
fclose(p->tmp_file); /* auto-deleted by lsx_tmpfile */
return SOX_SUCCESS;
}
sox_effect_handler_t const * lsx_reverse_effect_fn(void)
{
static sox_effect_handler_t handler = {
"reverse", NULL, SOX_EFF_MODIFY, NULL, start, flow, drain, stop, NULL, sizeof(priv_t)
};
return &handler;
}

@ -1,21 +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
*/
#include "sox_i.h"
#include "raw.h"
RAW_FORMAT2(s1, "s8", "sb", 8, 0, SIGN2)

@ -1,21 +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
*/
#include "sox_i.h"
#include "raw.h"
RAW_FORMAT2(s2, "s16", "sw", 16, 0, SIGN2)

@ -1,21 +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
*/
#include "sox_i.h"
#include "raw.h"
RAW_FORMAT1(s3, "s24", 24, 0, SIGN2)

@ -1,21 +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
*/
#include "sox_i.h"
#include "raw.h"
RAW_FORMAT2(s4, "s32", "sl", 32, 0, SIGN2)

@ -1,30 +0,0 @@
/* libSoX file format: SD2 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"
LSX_FORMAT_HANDLER(sd2)
{
static char const * const names[] = {"sd2", NULL};
static unsigned const write_encodings[] = {SOX_ENCODING_SIGN2, 24, 16, 8,0,0};
static sox_format_handler_t handler;
handler = *lsx_sndfile_format_fn();
handler.description = "Sound Designer II";
handler.names = names;
handler.write_formats = write_encodings;
return &handler;
}

@ -1,690 +0,0 @@
/* Silence effect for SoX
* by Heikki Leinonen (heilei@iki.fi) 25.03.2001
* Major Modifications by Chris Bagwell 06.08.2001
* Minor addition by Donnie Smith 13.08.2003
*
* This effect can delete samples from the start of a sound file
* until it sees a specified count of samples exceed a given threshold
* (any of the channels).
* This effect can also delete samples from the end of a sound file
* when it sees a specified count of samples below a given threshold
* (all channels).
* It may also be used to delete samples anywhere in a sound file.
* Thesholds can be given as either a percentage or in decibels.
*/
#include "sox_i.h"
#include <string.h>
/* Private data for silence effect. */
#define SILENCE_TRIM 0
#define SILENCE_TRIM_FLUSH 1
#define SILENCE_COPY 2
#define SILENCE_COPY_FLUSH 3
#define SILENCE_STOP 4
typedef struct {
char start;
int start_periods;
char *start_duration_str;
size_t start_duration;
double start_threshold;
char start_unit; /* "d" for decibels or "%" for percent. */
int restart;
sox_sample_t *start_holdoff;
size_t start_holdoff_offset;
size_t start_holdoff_end;
int start_found_periods;
char stop;
int stop_periods;
char *stop_duration_str;
size_t stop_duration;
double stop_threshold;
char stop_unit;
sox_sample_t *stop_holdoff;
size_t stop_holdoff_offset;
size_t stop_holdoff_end;
int stop_found_periods;
double *window;
double *window_current;
double *window_end;
size_t window_size;
double rms_sum;
char leave_silence;
/* State Machine */
char mode;
} priv_t;
static void clear_rms(sox_effect_t * effp)
{
priv_t * silence = (priv_t *) effp->priv;
memset(silence->window, 0,
silence->window_size * sizeof(double));
silence->window_current = silence->window;
silence->window_end = silence->window + silence->window_size;
silence->rms_sum = 0;
}
static int sox_silence_getopts(sox_effect_t * effp, int argc, char **argv)
{
priv_t * silence = (priv_t *) effp->priv;
int parse_count;
uint64_t temp;
const char *n;
--argc, ++argv;
/* check for option switches */
silence->leave_silence = sox_false;
if (argc > 0)
{
if (!strcmp("-l", *argv)) {
argc--; argv++;
silence->leave_silence = sox_true;
}
}
if (argc < 1)
return lsx_usage(effp);
/* Parse data related to trimming front side */
silence->start = sox_false;
if (sscanf(argv[0], "%d", &silence->start_periods) != 1)
return lsx_usage(effp);
if (silence->start_periods < 0)
{
lsx_fail("Periods must not be negative");
return(SOX_EOF);
}
argv++;
argc--;
if (silence->start_periods > 0)
{
silence->start = sox_true;
if (argc < 2)
return lsx_usage(effp);
/* We do not know the sample rate so we can not fully
* parse the duration info yet. So save argument off
* for future processing.
*/
silence->start_duration_str = lsx_strdup(argv[0]);
/* Perform a fake parse to do error checking */
n = lsx_parsesamples(0.,silence->start_duration_str,&temp,'s');
if (!n || *n)
return lsx_usage(effp);
silence->start_duration = temp;
parse_count = sscanf(argv[1], "%lf%c", &silence->start_threshold,
&silence->start_unit);
if (parse_count < 1)
return lsx_usage(effp);
else if (parse_count < 2)
silence->start_unit = '%';
argv++; argv++;
argc--; argc--;
}
silence->stop = sox_false;
/* Parse data needed for trimming of backside */
if (argc > 0)
{
if (argc < 3)
return lsx_usage(effp);
if (sscanf(argv[0], "%d", &silence->stop_periods) != 1)
return lsx_usage(effp);
if (silence->stop_periods < 0)
{
silence->stop_periods = -silence->stop_periods;
silence->restart = 1;
}
else
silence->restart = 0;
silence->stop = sox_true;
argv++;
argc--;
/* We do not know the sample rate so we can not fully
* parse the duration info yet. So save argument off
* for future processing.
*/
silence->stop_duration_str = lsx_strdup(argv[0]);
/* Perform a fake parse to do error checking */
n = lsx_parsesamples(0.,silence->stop_duration_str,&temp,'s');
if (!n || *n)
return lsx_usage(effp);
silence->stop_duration = temp;
parse_count = sscanf(argv[1], "%lf%c", &silence->stop_threshold,
&silence->stop_unit);
if (parse_count < 1)
return lsx_usage(effp);
else if (parse_count < 2)
silence->stop_unit = '%';
argv++; argv++;
argc--; argc--;
}
/* Error checking */
if (silence->start)
{
if ((silence->start_unit != '%') && (silence->start_unit != 'd'))
{
lsx_fail("Invalid unit specified");
return lsx_usage(effp);
}
if ((silence->start_unit == '%') && ((silence->start_threshold < 0.0)
|| (silence->start_threshold > 100.0)))
{
lsx_fail("silence threshold should be between 0.0 and 100.0 %%");
return (SOX_EOF);
}
if ((silence->start_unit == 'd') && (silence->start_threshold >= 0.0))
{
lsx_fail("silence threshold should be less than 0.0 dB");
return(SOX_EOF);
}
}
if (silence->stop)
{
if ((silence->stop_unit != '%') && (silence->stop_unit != 'd'))
{
lsx_fail("Invalid unit specified");
return(SOX_EOF);
}
if ((silence->stop_unit == '%') && ((silence->stop_threshold < 0.0) ||
(silence->stop_threshold > 100.0)))
{
lsx_fail("silence threshold should be between 0.0 and 100.0 %%");
return (SOX_EOF);
}
if ((silence->stop_unit == 'd') && (silence->stop_threshold >= 0.0))
{
lsx_fail("silence threshold should be less than 0.0 dB");
return(SOX_EOF);
}
}
return(SOX_SUCCESS);
}
static int sox_silence_start(sox_effect_t * effp)
{
priv_t *silence = (priv_t *)effp->priv;
uint64_t temp;
/* When you want to remove silence, small window sizes are
* better or else RMS will look like non-silence at
* aburpt changes from load to silence.
*/
silence->window_size = (effp->in_signal.rate / 50) *
effp->in_signal.channels;
silence->window = lsx_malloc(silence->window_size * sizeof(double));
clear_rms(effp);
/* Now that we know sample rate, reparse duration. */
if (silence->start)
{
if (lsx_parsesamples(effp->in_signal.rate, silence->start_duration_str,
&temp, 's') == NULL)
return lsx_usage(effp);
silence->start_duration = temp * effp->in_signal.channels;
}
if (silence->stop)
{
if (lsx_parsesamples(effp->in_signal.rate,silence->stop_duration_str,
&temp,'s') == NULL)
return lsx_usage(effp);
silence->stop_duration = temp * effp->in_signal.channels;
}
if (silence->start)
silence->mode = SILENCE_TRIM;
else
silence->mode = SILENCE_COPY;
silence->start_holdoff = lsx_malloc(sizeof(sox_sample_t)*silence->start_duration);
silence->start_holdoff_offset = 0;
silence->start_holdoff_end = 0;
silence->start_found_periods = 0;
silence->stop_holdoff = lsx_malloc(sizeof(sox_sample_t)*silence->stop_duration);
silence->stop_holdoff_offset = 0;
silence->stop_holdoff_end = 0;
silence->stop_found_periods = 0;
effp->out_signal.length = SOX_UNKNOWN_LEN; /* depends on input data */
return(SOX_SUCCESS);
}
static sox_bool aboveThreshold(sox_effect_t const * effp,
sox_sample_t value /* >= 0 */, double threshold, int unit)
{
/* When scaling low bit data, noise values got scaled way up */
/* Only consider the original bits when looking for silence */
sox_sample_t masked_value = value & (-1 << (32 - effp->in_signal.precision));
double scaled_value = (double)masked_value / SOX_SAMPLE_MAX;
if (unit == '%')
scaled_value *= 100;
else if (unit == 'd')
scaled_value = linear_to_dB(scaled_value);
return scaled_value > threshold;
}
static sox_sample_t compute_rms(sox_effect_t * effp, sox_sample_t sample)
{
priv_t * silence = (priv_t *) effp->priv;
double new_sum;
sox_sample_t rms;
new_sum = silence->rms_sum;
new_sum -= *silence->window_current;
new_sum += ((double)sample * (double)sample);
rms = sqrt(new_sum / silence->window_size);
return (rms);
}
static void update_rms(sox_effect_t * effp, sox_sample_t sample)
{
priv_t * silence = (priv_t *) effp->priv;
silence->rms_sum -= *silence->window_current;
*silence->window_current = ((double)sample * (double)sample);
silence->rms_sum += *silence->window_current;
silence->window_current++;
if (silence->window_current >= silence->window_end)
silence->window_current = silence->window;
}
/* Process signed long samples from ibuf to obuf. */
/* Return number of samples processed in isamp and osamp. */
static int sox_silence_flow(sox_effect_t * effp, const sox_sample_t *ibuf, sox_sample_t *obuf,
size_t *isamp, size_t *osamp)
{
priv_t * silence = (priv_t *) effp->priv;
int threshold;
size_t i, j;
size_t nrOfTicks, /* sometimes wide, sometimes non-wide samples */
nrOfInSamplesRead, nrOfOutSamplesWritten; /* non-wide samples */
nrOfInSamplesRead = 0;
nrOfOutSamplesWritten = 0;
switch (silence->mode)
{
case SILENCE_TRIM:
/* Reads and discards all input data until it detects a
* sample that is above the specified threshold. Turns on
* copy mode when detected.
* Need to make sure and copy input in groups of "channels" to
* prevent getting buffers out of sync.
* nrOfTicks counts wide samples here.
*/
silence_trim:
nrOfTicks = min((*isamp-nrOfInSamplesRead),
(*osamp-nrOfOutSamplesWritten)) /
effp->in_signal.channels;
for(i = 0; i < nrOfTicks; i++)
{
threshold = 0;
for (j = 0; j < effp->in_signal.channels; j++)
{
threshold |= aboveThreshold(effp,
compute_rms(effp, ibuf[j]),
silence->start_threshold,
silence->start_unit);
}
if (threshold)
{
/* Add to holdoff buffer */
for (j = 0; j < effp->in_signal.channels; j++)
{
update_rms(effp, *ibuf);
silence->start_holdoff[
silence->start_holdoff_end++] = *ibuf++;
nrOfInSamplesRead++;
}
if (silence->start_holdoff_end >=
silence->start_duration)
{
if (++silence->start_found_periods >=
silence->start_periods)
{
silence->mode = SILENCE_TRIM_FLUSH;
goto silence_trim_flush;
}
/* Trash holdoff buffer since its not
* needed. Start looking again.
*/
silence->start_holdoff_offset = 0;
silence->start_holdoff_end = 0;
}
}
else /* !above Threshold */
{
silence->start_holdoff_end = 0;
for (j = 0; j < effp->in_signal.channels; j++)
{
update_rms(effp, ibuf[j]);
}
ibuf += effp->in_signal.channels;
nrOfInSamplesRead += effp->in_signal.channels;
}
} /* for nrOfTicks */
break;
case SILENCE_TRIM_FLUSH:
/* nrOfTicks counts non-wide samples here. */
silence_trim_flush:
nrOfTicks = min((silence->start_holdoff_end -
silence->start_holdoff_offset),
(*osamp-nrOfOutSamplesWritten));
nrOfTicks -= nrOfTicks % effp->in_signal.channels;
for(i = 0; i < nrOfTicks; i++)
{
*obuf++ = silence->start_holdoff[silence->start_holdoff_offset++];
nrOfOutSamplesWritten++;
}
/* If fully drained holdoff then switch to copy mode */
if (silence->start_holdoff_offset == silence->start_holdoff_end)
{
silence->start_holdoff_offset = 0;
silence->start_holdoff_end = 0;
silence->mode = SILENCE_COPY;
goto silence_copy;
}
break;
case SILENCE_COPY:
/* Attempts to copy samples into output buffer.
*
* Case B:
* If not looking for silence to terminate copy then
* blindly copy data into output buffer.
*
* Case A:
*
* Case 1a:
* If previous silence was detect then see if input sample is
* above threshold. If found then flush out hold off buffer
* and copy over to output buffer.
*
* Case 1b:
* If no previous silence detect then see if input sample
* is above threshold. If found then copy directly
* to output buffer.
*
* Case 2:
* If not above threshold then silence is detect so
* store in hold off buffer and do not write to output
* buffer. Even though it wasn't put in output
* buffer, inform user that input was consumed.
*
* If hold off buffer is full after this then stop
* copying data and discard data in hold off buffer.
*
* Special leave_silence logic:
*
* During this mode, go ahead and copy input
* samples to output buffer instead of holdoff buffer
* Then also short ciruit any flushes that would occur
* when non-silence is detect since samples were already
* copied. This has the effect of always leaving
* holdoff[] amount of silence but deleting any
* beyond that amount.
*
* nrOfTicks counts wide samples here.
*/
silence_copy:
nrOfTicks = min((*isamp-nrOfInSamplesRead),
(*osamp-nrOfOutSamplesWritten)) /
effp->in_signal.channels;
if (silence->stop)
{
/* Case A */
for(i = 0; i < nrOfTicks; i++)
{
threshold = 1;
for (j = 0; j < effp->in_signal.channels; j++)
{
threshold &= aboveThreshold(effp,
compute_rms(effp, ibuf[j]),
silence->stop_threshold,
silence->stop_unit);
}
/* Case 1a
* If above threshold, check to see if we where holding
* off previously. If so then flush this buffer.
* We haven't incremented any pointers yet so nothing
* is lost.
*
* If user wants to leave_silence, then we
* were already copying the data and so no
* need to flush the old data. Just resume
* copying as if we were not holding off.
*/
if (threshold && silence->stop_holdoff_end
&& !silence->leave_silence)
{
silence->mode = SILENCE_COPY_FLUSH;
goto silence_copy_flush;
}
/* Case 1b */
else if (threshold)
{
/* Not holding off so copy into output buffer */
for (j = 0; j < effp->in_signal.channels; j++)
{
update_rms(effp, *ibuf);
*obuf++ = *ibuf++;
nrOfInSamplesRead++;
nrOfOutSamplesWritten++;
}
}
/* Case 2 */
else if (!threshold)
{
/* Add to holdoff buffer */
for (j = 0; j < effp->in_signal.channels; j++)
{
update_rms(effp, *ibuf);
if (silence->leave_silence) {
*obuf++ = *ibuf;
nrOfOutSamplesWritten++;
}
silence->stop_holdoff[
silence->stop_holdoff_end++] = *ibuf++;
nrOfInSamplesRead++;
}
/* Check if holdoff buffer is greater than duration
*/
if (silence->stop_holdoff_end >=
silence->stop_duration)
{
/* Increment found counter and see if this
* is the last period. If so then exit.
*/
if (++silence->stop_found_periods >=
silence->stop_periods)
{
silence->stop_holdoff_offset = 0;
silence->stop_holdoff_end = 0;
if (!silence->restart)
{
*isamp = nrOfInSamplesRead;
*osamp = nrOfOutSamplesWritten;
silence->mode = SILENCE_STOP;
/* Return SOX_EOF since no more processing */
return (SOX_EOF);
}
else
{
silence->stop_found_periods = 0;
silence->start_found_periods = 0;
silence->start_holdoff_offset = 0;
silence->start_holdoff_end = 0;
clear_rms(effp);
silence->mode = SILENCE_TRIM;
goto silence_trim;
}
}
else
{
/* Flush this buffer and start
* looking again.
*/
silence->mode = SILENCE_COPY_FLUSH;
goto silence_copy_flush;
}
break;
} /* Filled holdoff buffer */
} /* Detected silence */
} /* For # of samples */
} /* Trimming off backend */
else /* !(silence->stop) */
{
/* Case B */
memcpy(obuf, ibuf, sizeof(sox_sample_t)*nrOfTicks*
effp->in_signal.channels);
nrOfInSamplesRead += (nrOfTicks*effp->in_signal.channels);
nrOfOutSamplesWritten += (nrOfTicks*effp->in_signal.channels);
}
break;
case SILENCE_COPY_FLUSH:
/* nrOfTicks counts non-wide samples here. */
silence_copy_flush:
nrOfTicks = min((silence->stop_holdoff_end -
silence->stop_holdoff_offset),
(*osamp-nrOfOutSamplesWritten));
nrOfTicks -= nrOfTicks % effp->in_signal.channels;
for(i = 0; i < nrOfTicks; i++)
{
*obuf++ = silence->stop_holdoff[silence->stop_holdoff_offset++];
nrOfOutSamplesWritten++;
}
/* If fully drained holdoff then return to copy mode */
if (silence->stop_holdoff_offset == silence->stop_holdoff_end)
{
silence->stop_holdoff_offset = 0;
silence->stop_holdoff_end = 0;
silence->mode = SILENCE_COPY;
goto silence_copy;
}
break;
case SILENCE_STOP:
/* This code can't be reached. */
nrOfInSamplesRead = *isamp;
break;
}
*isamp = nrOfInSamplesRead;
*osamp = nrOfOutSamplesWritten;
return (SOX_SUCCESS);
}
static int sox_silence_drain(sox_effect_t * effp, sox_sample_t *obuf, size_t *osamp)
{
priv_t * silence = (priv_t *) effp->priv;
size_t i;
size_t nrOfTicks, nrOfOutSamplesWritten = 0; /* non-wide samples */
/* Only if in flush mode will there be possible samples to write
* out during drain() call.
*/
if (silence->mode == SILENCE_COPY_FLUSH ||
silence->mode == SILENCE_COPY)
{
nrOfTicks = min((silence->stop_holdoff_end -
silence->stop_holdoff_offset), *osamp);
nrOfTicks -= nrOfTicks % effp->in_signal.channels;
for(i = 0; i < nrOfTicks; i++)
{
*obuf++ = silence->stop_holdoff[silence->stop_holdoff_offset++];
nrOfOutSamplesWritten++;
}
/* If fully drained holdoff then stop */
if (silence->stop_holdoff_offset == silence->stop_holdoff_end)
{
silence->stop_holdoff_offset = 0;
silence->stop_holdoff_end = 0;
silence->mode = SILENCE_STOP;
}
}
*osamp = nrOfOutSamplesWritten;
if (silence->mode == SILENCE_STOP || *osamp == 0)
return SOX_EOF;
else
return SOX_SUCCESS;
}
static int sox_silence_stop(sox_effect_t * effp)
{
priv_t * silence = (priv_t *) effp->priv;
free(silence->window);
free(silence->start_holdoff);
free(silence->stop_holdoff);
return(SOX_SUCCESS);
}
static int lsx_kill(sox_effect_t * effp)
{
priv_t * silence = (priv_t *) effp->priv;
free(silence->start_duration_str);
free(silence->stop_duration_str);
return SOX_SUCCESS;
}
static sox_effect_handler_t sox_silence_effect = {
"silence",
"[ -l ] above_periods [ duration threshold[d|%] ] [ below_periods duration threshold[d|%] ]",
SOX_EFF_MCHAN | SOX_EFF_MODIFY | SOX_EFF_LENGTH,
sox_silence_getopts,
sox_silence_start,
sox_silence_flow,
sox_silence_drain,
sox_silence_stop,
lsx_kill, sizeof(priv_t)
};
const sox_effect_handler_t *lsx_silence_effect_fn(void)
{
return &sox_silence_effect;
}

@ -1,157 +0,0 @@
/* Effect: sinc filters Copyright (c) 2008-9 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 "dft_filter.h"
#include <string.h>
typedef struct {
dft_filter_priv_t base;
double att, beta, phase, Fc0, Fc1, tbw0, tbw1;
int num_taps[2];
sox_bool round;
} priv_t;
static int create(sox_effect_t * effp, int argc, char * * argv)
{
priv_t * p = (priv_t *)effp->priv;
dft_filter_priv_t * b = &p->base;
char * parse_ptr = argv[0];
int i = 0;
lsx_getopt_t optstate;
lsx_getopt_init(argc, argv, "+ra:b:p:MILt:n:", NULL, lsx_getopt_flag_none, 1, &optstate);
b->filter_ptr = &b->filter;
p->phase = 50;
p->beta = -1;
while (i < 2) {
int c = 1;
while (c && (c = lsx_getopt(&optstate)) != -1) switch (c) {
char * parse_ptr2;
case 'r': p->round = sox_true; break;
GETOPT_NUMERIC(optstate, 'a', att, 40 , 180)
GETOPT_NUMERIC(optstate, 'b', beta, 0 , 256)
GETOPT_NUMERIC(optstate, 'p', phase, 0, 100)
case 'M': p->phase = 0; break;
case 'I': p->phase = 25; break;
case 'L': p->phase = 50; break;
GETOPT_NUMERIC(optstate, 'n', num_taps[1], 11, 32767)
case 't': p->tbw1 = lsx_parse_frequency(optstate.arg, &parse_ptr2);
if (p->tbw1 < 1 || *parse_ptr2) return lsx_usage(effp);
break;
default: c = 0;
}
if ((p->att && p->beta >= 0) || (p->tbw1 && p->num_taps[1]))
return lsx_usage(effp);
if (!i || !p->Fc1)
p->tbw0 = p->tbw1, p->num_taps[0] = p->num_taps[1];
if (!i++ && optstate.ind < argc) {
if (*(parse_ptr = argv[optstate.ind++]) != '-')
p->Fc0 = lsx_parse_frequency(parse_ptr, &parse_ptr);
if (*parse_ptr == '-')
p->Fc1 = lsx_parse_frequency(parse_ptr + 1, &parse_ptr);
}
}
return optstate.ind != argc || p->Fc0 < 0 || p->Fc1 < 0 || *parse_ptr ?
lsx_usage(effp) : SOX_SUCCESS;
}
static void invert(double * h, int n)
{
int i;
for (i = 0; i < n; ++i)
h[i] = -h[i];
h[(n - 1) / 2] += 1;
}
static double * lpf(double Fn, double Fc, double tbw, int * num_taps, double att, double * beta, sox_bool round)
{
int n = *num_taps;
if ((Fc /= Fn) <= 0 || Fc >= 1) {
*num_taps = 0;
return NULL;
}
att = att? att : 120;
lsx_kaiser_params(att, Fc, (tbw? tbw / Fn : .05) * .5, beta, num_taps);
if (!n) {
n = *num_taps;
*num_taps = range_limit(n, 11, 32767);
if (round)
*num_taps = 1 + 2 * (int)((int)((*num_taps / 2) * Fc + .5) / Fc + .5);
lsx_report("num taps = %i (from %i)", *num_taps, n);
}
return lsx_make_lpf(*num_taps |= 1, Fc, *beta, 0., 1., sox_false);
}
static int start(sox_effect_t * effp)
{
priv_t * p = (priv_t *)effp->priv;
dft_filter_t * f = p->base.filter_ptr;
if (!f->num_taps) {
double Fn = effp->in_signal.rate * .5;
double * h[2];
int i, n, post_peak, longer;
if (p->Fc0 >= Fn || p->Fc1 >= Fn) {
lsx_fail("filter frequency must be less than sample-rate / 2");
return SOX_EOF;
}
h[0] = lpf(Fn, p->Fc0, p->tbw0, &p->num_taps[0], p->att, &p->beta,p->round);
h[1] = lpf(Fn, p->Fc1, p->tbw1, &p->num_taps[1], p->att, &p->beta,p->round);
if (h[0])
invert(h[0], p->num_taps[0]);
longer = p->num_taps[1] > p->num_taps[0];
n = p->num_taps[longer];
if (h[0] && h[1]) {
for (i = 0; i < p->num_taps[!longer]; ++i)
h[longer][i + (n - p->num_taps[!longer])/2] += h[!longer][i];
if (p->Fc0 < p->Fc1)
invert(h[longer], n);
free(h[!longer]);
}
if (p->phase != 50)
lsx_fir_to_phase(&h[longer], &n, &post_peak, p->phase);
else post_peak = n >> 1;
if (effp->global_info->plot != sox_plot_off) {
char title[100];
sprintf(title, "SoX effect: sinc filter freq=%g-%g",
p->Fc0, p->Fc1? p->Fc1 : Fn);
lsx_plot_fir(h[longer], n, effp->in_signal.rate,
effp->global_info->plot, title, -p->beta * 10 - 25, 5.);
return SOX_EOF;
}
lsx_set_dft_filter(f, h[longer], n, post_peak);
}
return lsx_dft_filter_effect_fn()->start(effp);
}
sox_effect_handler_t const * lsx_sinc_effect_fn(void)
{
static sox_effect_handler_t handler;
handler = *lsx_dft_filter_effect_fn();
handler.name = "sinc";
handler.usage = "[-a att|-b beta] [-p phase|-M|-I|-L] [-t tbw|-n taps] [freqHP][-freqLP [-t tbw|-n taps]]";
handler.getopts = create;
handler.start = start;
handler.priv_size = sizeof(priv_t);
return &handler;
}

@ -1,141 +0,0 @@
/* libSoX effect: Skeleton effect used as sample for creating new effects.
*
* Copyright 1999-2008 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"
/* Private data for effect */
typedef struct {
int localdata;
} priv_t;
/*
* Process command-line options but don't do other
* initialization now: effp->in_signal & effp->out_signal are not
* yet filled in.
*/
static int getopts(sox_effect_t * effp, int argc, char UNUSED **argv)
{
priv_t * UNUSED p = (priv_t *)effp->priv;
if (argc != 2)
return lsx_usage(effp);
p->localdata = atoi(argv[1]);
return p->localdata > 0 ? SOX_SUCCESS : SOX_EOF;
}
/*
* Prepare processing.
* Do all initializations.
*/
static int start(sox_effect_t * effp)
{
if (effp->out_signal.channels == 1) {
lsx_fail("Can't run on mono data.");
return SOX_EOF;
}
return SOX_SUCCESS;
}
/*
* Process up to *isamp samples from ibuf and produce up to *osamp samples
* in obuf. Write back the actual numbers of samples to *isamp and *osamp.
* Return SOX_SUCCESS or, if error occurs, SOX_EOF.
*/
static int flow(sox_effect_t * effp, const sox_sample_t *ibuf, sox_sample_t *obuf,
size_t *isamp, size_t *osamp)
{
priv_t * UNUSED p = (priv_t *)effp->priv;
size_t len, done;
switch (effp->out_signal.channels) {
case 2:
/* Length to process will be buffer length / 2 since we
* work with two samples at a time.
*/
len = min(*isamp, *osamp) / 2;
for (done = 0; done < len; done++)
{
obuf[0] = ibuf[0];
obuf[1] = ibuf[1];
/* Advance buffer by 2 samples */
ibuf += 2;
obuf += 2;
}
*isamp = len * 2;
*osamp = len * 2;
break;
}
return SOX_SUCCESS;
}
/*
* Drain out remaining samples if the effect generates any.
*/
static int drain(sox_effect_t UNUSED * effp, sox_sample_t UNUSED *obuf, size_t *osamp)
{
*osamp = 0;
/* Return SOX_EOF when drain
* will not output any more samples.
* *osamp == 0 also indicates that.
*/
return SOX_EOF;
}
/*
* Do anything required when you stop reading samples.
*/
static int stop(sox_effect_t UNUSED * effp)
{
return SOX_SUCCESS;
}
/*
* Do anything required when you kill an effect.
* (free allocated memory, etc.)
*/
static int lsx_kill(sox_effect_t UNUSED * effp)
{
return SOX_SUCCESS;
}
/*
* Function returning effect descriptor. This should be the only
* externally visible object.
*/
const sox_effect_handler_t *lsx_skel_effect_fn(void);
const sox_effect_handler_t *lsx_skel_effect_fn(void)
{
/*
* Effect descriptor.
* If no specific processing is needed for any of
* the 6 functions, then the function above can be deleted
* and NULL used in place of the its name below.
*/
static sox_effect_handler_t sox_skel_effect = {
"skel", "[OPTION]", SOX_EFF_MCHAN,
getopts, start, flow, drain, stop, lsx_kill, sizeof(priv_t)
};
return &sox_skel_effect;
}

@ -1,532 +0,0 @@
/* libSoX libsndfile formats.
*
* Copyright 2007 Reuben Thomas <rrt@sc3d.org>
* Copyright 1999-2005 Erik de Castro Lopo <eridk@mega-nerd.com>
*
* 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 <assert.h>
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include <sndfile.h>
#define LOG_MAX 2048 /* As per the SFC_GET_LOG_INFO example */
static const char* const sndfile_library_names[] =
{
#ifdef DL_LIBSNDFILE
"libsndfile",
"libsndfile-1",
"cygsndfile-1",
#endif
NULL
};
#ifdef DL_LIBSNDFILE
#define SNDFILE_FUNC LSX_DLENTRY_DYNAMIC
#define SNDFILE_FUNC_STOP LSX_DLENTRY_STUB
#else
#define SNDFILE_FUNC LSX_DLENTRY_STATIC
#ifdef HACKED_LSF
#define SNDFILE_FUNC_STOP LSX_DLENTRY_STATIC
#else
#define SNDFILE_FUNC_STOP LSX_DLENTRY_STUB
#endif
#endif /* DL_LIBSNDFILE */
#define SNDFILE_FUNC_OPEN(f,x) \
SNDFILE_FUNC(f,x, SNDFILE*, sf_open_virtual, (SF_VIRTUAL_IO *sfvirtual, int mode, SF_INFO *sfinfo, void *user_data))
#define SNDFILE_FUNC_ENTRIES(f,x) \
SNDFILE_FUNC_OPEN(f,x) \
SNDFILE_FUNC_STOP(f,x, int, sf_stop, (SNDFILE *sndfile)) \
SNDFILE_FUNC(f,x, int, sf_close, (SNDFILE *sndfile)) \
SNDFILE_FUNC(f,x, int, sf_format_check, (const SF_INFO *info)) \
SNDFILE_FUNC(f,x, int, sf_command, (SNDFILE *sndfile, int command, void *data, int datasize)) \
SNDFILE_FUNC(f,x, sf_count_t, sf_read_int, (SNDFILE *sndfile, int *ptr, sf_count_t items)) \
SNDFILE_FUNC(f,x, sf_count_t, sf_write_int, (SNDFILE *sndfile, const int *ptr, sf_count_t items)) \
SNDFILE_FUNC(f,x, sf_count_t, sf_seek, (SNDFILE *sndfile, sf_count_t frames, int whence)) \
SNDFILE_FUNC(f,x, const char*, sf_strerror, (SNDFILE *sndfile))
/* Private data for sndfile files */
typedef struct {
SNDFILE *sf_file;
SF_INFO *sf_info;
char * log_buffer;
char const * log_buffer_ptr;
LSX_DLENTRIES_TO_PTRS(SNDFILE_FUNC_ENTRIES, sndfile_dl);
} priv_t;
/*
* Drain LSF's wonderful log buffer
*/
static void drain_log_buffer(sox_format_t * ft)
{
priv_t * sf = (priv_t *)ft->priv;
sf->sf_command(sf->sf_file, SFC_GET_LOG_INFO, sf->log_buffer, LOG_MAX);
while (*sf->log_buffer_ptr) {
static char const warning_prefix[] = "*** Warning : ";
char const * end = strchr(sf->log_buffer_ptr, '\n');
if (!end)
end = strchr(sf->log_buffer_ptr, '\0');
if (!strncmp(sf->log_buffer_ptr, warning_prefix, strlen(warning_prefix))) {
sf->log_buffer_ptr += strlen(warning_prefix);
lsx_warn("`%s': %.*s",
ft->filename, (int)(end - sf->log_buffer_ptr), sf->log_buffer_ptr);
} else
lsx_debug("`%s': %.*s",
ft->filename, (int)(end - sf->log_buffer_ptr), sf->log_buffer_ptr);
sf->log_buffer_ptr = end;
if (*sf->log_buffer_ptr == '\n')
++sf->log_buffer_ptr;
}
}
/* Make libsndfile subtype from sample encoding and size */
static int ft_enc(unsigned size, sox_encoding_t e)
{
if (e == SOX_ENCODING_ULAW && size == 8) return SF_FORMAT_ULAW;
if (e == SOX_ENCODING_ALAW && size == 8) return SF_FORMAT_ALAW;
if (e == SOX_ENCODING_SIGN2 && size == 8) return SF_FORMAT_PCM_S8;
if (e == SOX_ENCODING_SIGN2 && size == 16) return SF_FORMAT_PCM_16;
if (e == SOX_ENCODING_SIGN2 && size == 24) return SF_FORMAT_PCM_24;
if (e == SOX_ENCODING_SIGN2 && size == 32) return SF_FORMAT_PCM_32;
if (e == SOX_ENCODING_UNSIGNED && size == 8) return SF_FORMAT_PCM_U8;
if (e == SOX_ENCODING_FLOAT && size == 32) return SF_FORMAT_FLOAT;
if (e == SOX_ENCODING_FLOAT && size == 64) return SF_FORMAT_DOUBLE;
if (e == SOX_ENCODING_G721 && size == 4) return SF_FORMAT_G721_32;
if (e == SOX_ENCODING_G723 && size == 3) return SF_FORMAT_G723_24;
if (e == SOX_ENCODING_G723 && size == 5) return SF_FORMAT_G723_40;
if (e == SOX_ENCODING_MS_ADPCM && size == 4) return SF_FORMAT_MS_ADPCM;
if (e == SOX_ENCODING_IMA_ADPCM && size == 4) return SF_FORMAT_IMA_ADPCM;
if (e == SOX_ENCODING_OKI_ADPCM && size == 4) return SF_FORMAT_VOX_ADPCM;
if (e == SOX_ENCODING_DPCM && size == 8) return SF_FORMAT_DPCM_8;
if (e == SOX_ENCODING_DPCM && size == 16) return SF_FORMAT_DPCM_16;
if (e == SOX_ENCODING_DWVW && size == 12) return SF_FORMAT_DWVW_12;
if (e == SOX_ENCODING_DWVW && size == 16) return SF_FORMAT_DWVW_16;
if (e == SOX_ENCODING_DWVW && size == 24) return SF_FORMAT_DWVW_24;
if (e == SOX_ENCODING_DWVWN && size == 0) return SF_FORMAT_DWVW_N;
if (e == SOX_ENCODING_GSM && size == 0) return SF_FORMAT_GSM610;
if (e == SOX_ENCODING_FLAC && size == 8) return SF_FORMAT_PCM_S8;
if (e == SOX_ENCODING_FLAC && size == 16) return SF_FORMAT_PCM_16;
if (e == SOX_ENCODING_FLAC && size == 24) return SF_FORMAT_PCM_24;
if (e == SOX_ENCODING_FLAC && size == 32) return SF_FORMAT_PCM_32;
return 0; /* Bad encoding */
}
/* Convert format's encoding type to libSoX encoding type & size. */
static sox_encoding_t sox_enc(int ft_encoding, unsigned * size)
{
int sub = ft_encoding & SF_FORMAT_SUBMASK;
int type = ft_encoding & SF_FORMAT_TYPEMASK;
if (type == SF_FORMAT_FLAC) switch (sub) {
case SF_FORMAT_PCM_S8 : *size = 8; return SOX_ENCODING_FLAC;
case SF_FORMAT_PCM_16 : *size = 16; return SOX_ENCODING_FLAC;
case SF_FORMAT_PCM_24 : *size = 24; return SOX_ENCODING_FLAC;
}
switch (sub) {
case SF_FORMAT_ULAW : *size = 8; return SOX_ENCODING_ULAW;
case SF_FORMAT_ALAW : *size = 8; return SOX_ENCODING_ALAW;
case SF_FORMAT_PCM_S8 : *size = 8; return SOX_ENCODING_SIGN2;
case SF_FORMAT_PCM_16 : *size = 16; return SOX_ENCODING_SIGN2;
case SF_FORMAT_PCM_24 : *size = 24; return SOX_ENCODING_SIGN2;
case SF_FORMAT_PCM_32 : *size = 32; return SOX_ENCODING_SIGN2;
case SF_FORMAT_PCM_U8 : *size = 8; return SOX_ENCODING_UNSIGNED;
case SF_FORMAT_FLOAT : *size = 32; return SOX_ENCODING_FLOAT;
case SF_FORMAT_DOUBLE : *size = 64; return SOX_ENCODING_FLOAT;
case SF_FORMAT_G721_32 : *size = 4; return SOX_ENCODING_G721;
case SF_FORMAT_G723_24 : *size = 3; return SOX_ENCODING_G723;
case SF_FORMAT_G723_40 : *size = 5; return SOX_ENCODING_G723;
case SF_FORMAT_MS_ADPCM : *size = 4; return SOX_ENCODING_MS_ADPCM;
case SF_FORMAT_IMA_ADPCM: *size = 4; return SOX_ENCODING_IMA_ADPCM;
case SF_FORMAT_VOX_ADPCM: *size = 4; return SOX_ENCODING_OKI_ADPCM;
case SF_FORMAT_DPCM_8 : *size = 8; return SOX_ENCODING_DPCM;
case SF_FORMAT_DPCM_16 : *size = 16; return SOX_ENCODING_DPCM;
case SF_FORMAT_DWVW_12 : *size = 12; return SOX_ENCODING_DWVW;
case SF_FORMAT_DWVW_16 : *size = 16; return SOX_ENCODING_DWVW;
case SF_FORMAT_DWVW_24 : *size = 24; return SOX_ENCODING_DWVW;
case SF_FORMAT_DWVW_N : *size = 0; return SOX_ENCODING_DWVWN;
case SF_FORMAT_GSM610 : *size = 0; return SOX_ENCODING_GSM;
default : *size = 0; return SOX_ENCODING_UNKNOWN;
}
}
static struct {
const char *ext;
int format;
} format_map[] =
{
{ "aif", SF_FORMAT_AIFF },
{ "aiff", SF_FORMAT_AIFF },
{ "wav", SF_FORMAT_WAV },
{ "au", SF_FORMAT_AU },
{ "snd", SF_FORMAT_AU },
{ "caf", SF_FORMAT_CAF },
{ "flac", SF_FORMAT_FLAC },
{ "wve", SF_FORMAT_WVE },
{ "ogg", SF_FORMAT_OGG },
{ "svx", SF_FORMAT_SVX },
{ "8svx", SF_FORMAT_SVX },
{ "paf", SF_ENDIAN_BIG | SF_FORMAT_PAF },
{ "fap", SF_ENDIAN_LITTLE | SF_FORMAT_PAF },
{ "gsm", SF_FORMAT_RAW | SF_FORMAT_GSM610 },
{ "nist", SF_FORMAT_NIST },
{ "sph", SF_FORMAT_NIST },
{ "ircam", SF_FORMAT_IRCAM },
{ "sf", SF_FORMAT_IRCAM },
{ "voc", SF_FORMAT_VOC },
{ "w64", SF_FORMAT_W64 },
{ "raw", SF_FORMAT_RAW },
{ "mat4", SF_FORMAT_MAT4 },
{ "mat5", SF_FORMAT_MAT5 },
{ "mat", SF_FORMAT_MAT4 },
{ "pvf", SF_FORMAT_PVF },
{ "sds", SF_FORMAT_SDS },
{ "sd2", SF_FORMAT_SD2 },
{ "vox", SF_FORMAT_RAW | SF_FORMAT_VOX_ADPCM },
{ "xi", SF_FORMAT_XI }
};
static int sf_stop_stub(SNDFILE *sndfile UNUSED)
{
return 1;
}
static sf_count_t vio_get_filelen(void *user_data)
{
sox_format_t *ft = (sox_format_t *)user_data;
/* lsf excepts unbuffered I/O behavior for get_filelen() so force that */
lsx_flush(ft);
return (sf_count_t)lsx_filelength((sox_format_t *)user_data);
}
static sf_count_t vio_seek(sf_count_t offset, int whence, void *user_data)
{
return lsx_seeki((sox_format_t *)user_data, (off_t)offset, whence);
}
static sf_count_t vio_read(void *ptr, sf_count_t count, void *user_data)
{
return lsx_readbuf((sox_format_t *)user_data, ptr, (size_t)count);
}
static sf_count_t vio_write(const void *ptr, sf_count_t count, void *user_data)
{
return lsx_writebuf((sox_format_t *)user_data, ptr, (size_t)count);
}
static sf_count_t vio_tell(void *user_data)
{
return lsx_tell((sox_format_t *)user_data);
}
static SF_VIRTUAL_IO vio =
{
vio_get_filelen,
vio_seek,
vio_read,
vio_write,
vio_tell
};
/* Convert file name or type to libsndfile format */
static int name_to_format(const char *name)
{
int k;
#define FILE_TYPE_BUFLEN (size_t)15
char buffer[FILE_TYPE_BUFLEN + 1], *cptr;
if ((cptr = strrchr(name, '.')) != NULL) {
strncpy(buffer, cptr + 1, FILE_TYPE_BUFLEN);
buffer[FILE_TYPE_BUFLEN] = '\0';
for (k = 0; buffer[k]; k++)
buffer[k] = tolower((buffer[k]));
} else {
strncpy(buffer, name, FILE_TYPE_BUFLEN);
buffer[FILE_TYPE_BUFLEN] = '\0';
}
for (k = 0; k < (int)(sizeof(format_map) / sizeof(format_map [0])); k++) {
if (strcmp(buffer, format_map[k].ext) == 0)
return format_map[k].format;
}
return 0;
}
static int start(sox_format_t * ft)
{
priv_t * sf = (priv_t *)ft->priv;
int subtype = ft_enc(ft->encoding.bits_per_sample? ft->encoding.bits_per_sample : ft->signal.precision, ft->encoding.encoding);
int open_library_result;
LSX_DLLIBRARY_OPEN(
sf,
sndfile_dl,
SNDFILE_FUNC_ENTRIES,
"libsndfile library",
sndfile_library_names,
open_library_result);
if (open_library_result)
return SOX_EOF;
sf->log_buffer_ptr = sf->log_buffer = lsx_malloc((size_t)LOG_MAX);
sf->sf_info = lsx_calloc(1, sizeof(SF_INFO));
/* Copy format info */
if (subtype) {
if (strcmp(ft->filetype, "sndfile") == 0)
sf->sf_info->format = name_to_format(ft->filename) | subtype;
else
sf->sf_info->format = name_to_format(ft->filetype) | subtype;
}
sf->sf_info->samplerate = (int)ft->signal.rate;
sf->sf_info->channels = ft->signal.channels;
if (ft->signal.channels)
sf->sf_info->frames = ft->signal.length / ft->signal.channels;
return SOX_SUCCESS;
}
static int check_read_params(sox_format_t * ft, unsigned channels,
sox_rate_t rate, sox_encoding_t encoding, unsigned bits_per_sample, uint64_t length)
{
ft->signal.length = length;
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 (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;
}
/*
* Open file in sndfile.
*/
static int startread(sox_format_t * ft)
{
priv_t * sf = (priv_t *)ft->priv;
unsigned bits_per_sample;
sox_encoding_t encoding;
sox_rate_t rate;
if (start(ft) == SOX_EOF)
return SOX_EOF;
sf->sf_file = sf->sf_open_virtual(&vio, SFM_READ, sf->sf_info, ft);
drain_log_buffer(ft);
if (sf->sf_file == NULL) {
memset(ft->sox_errstr, 0, sizeof(ft->sox_errstr));
strncpy(ft->sox_errstr, sf->sf_strerror(sf->sf_file), sizeof(ft->sox_errstr)-1);
free(sf->sf_file);
return SOX_EOF;
}
if (!(encoding = sox_enc(sf->sf_info->format, &bits_per_sample))) {
lsx_fail_errno(ft, SOX_EFMT, "unsupported sndfile encoding %#x", sf->sf_info->format);
return SOX_EOF;
}
/* Don't believe LSF's rate for raw files */
if ((sf->sf_info->format & SF_FORMAT_TYPEMASK) == SF_FORMAT_RAW && !ft->signal.rate) {
lsx_warn("`%s': sample rate not specified; trying 8kHz", ft->filename);
rate = 8000;
}
else rate = sf->sf_info->samplerate;
if ((sf->sf_info->format & SF_FORMAT_SUBMASK) == SF_FORMAT_FLOAT) {
sf->sf_command(sf->sf_file, SFC_SET_SCALE_FLOAT_INT_READ, NULL, SF_TRUE);
sf->sf_command(sf->sf_file, SFC_SET_CLIPPING, NULL, SF_TRUE);
}
#if 0 /* FIXME */
sox_append_comments(&ft->oob.comments, buf);
#endif
return check_read_params(ft, (unsigned)sf->sf_info->channels, rate,
encoding, bits_per_sample, (uint64_t)(sf->sf_info->frames * sf->sf_info->channels));
}
/*
* Read up to len samples of type sox_sample_t from file into buf[].
* Return number of samples read.
*/
static size_t read_samples(sox_format_t * ft, sox_sample_t *buf, size_t len)
{
priv_t * sf = (priv_t *)ft->priv;
/* FIXME: We assume int == sox_sample_t here */
return (size_t)sf->sf_read_int(sf->sf_file, (int *)buf, (sf_count_t)len);
}
/*
* Close file for libsndfile (this doesn't close the file handle)
*/
static int stopread(sox_format_t * ft)
{
priv_t * sf = (priv_t *)ft->priv;
sf->sf_stop(sf->sf_file);
drain_log_buffer(ft);
sf->sf_close(sf->sf_file);
LSX_DLLIBRARY_CLOSE(sf, sndfile_dl);
return SOX_SUCCESS;
}
static int startwrite(sox_format_t * ft)
{
priv_t * sf = (priv_t *)ft->priv;
if (start(ft) == SOX_EOF)
return SOX_EOF;
/* If output format is invalid, try to find a sensible default */
if (!sf->sf_format_check(sf->sf_info)) {
SF_FORMAT_INFO format_info;
int i, count;
sf->sf_command(sf->sf_file, SFC_GET_SIMPLE_FORMAT_COUNT, &count, (int) sizeof(int));
for (i = 0; i < count; i++) {
format_info.format = i;
sf->sf_command(sf->sf_file, SFC_GET_SIMPLE_FORMAT, &format_info, (int) sizeof(format_info));
if ((format_info.format & SF_FORMAT_TYPEMASK) == (sf->sf_info->format & SF_FORMAT_TYPEMASK)) {
sf->sf_info->format = format_info.format;
/* FIXME: Print out exactly what we chose, needs sndfile ->
sox encoding conversion functions */
break;
}
}
if (!sf->sf_format_check(sf->sf_info)) {
lsx_fail("cannot find a usable output encoding");
return SOX_EOF;
}
if ((sf->sf_info->format & SF_FORMAT_TYPEMASK) != SF_FORMAT_RAW)
lsx_warn("cannot use desired output encoding, choosing default");
}
sf->sf_file = sf->sf_open_virtual(&vio, SFM_WRITE, sf->sf_info, ft);
drain_log_buffer(ft);
if (sf->sf_file == NULL) {
memset(ft->sox_errstr, 0, sizeof(ft->sox_errstr));
strncpy(ft->sox_errstr, sf->sf_strerror(sf->sf_file), sizeof(ft->sox_errstr)-1);
free(sf->sf_file);
return SOX_EOF;
}
if ((sf->sf_info->format & SF_FORMAT_SUBMASK) == SF_FORMAT_FLOAT)
sf->sf_command(sf->sf_file, SFC_SET_SCALE_INT_FLOAT_WRITE, NULL, SF_TRUE);
return SOX_SUCCESS;
}
/*
* Write len samples of type sox_sample_t from buf[] to file.
* Return number of samples written.
*/
static size_t write_samples(sox_format_t * ft, const sox_sample_t *buf, size_t len)
{
priv_t * sf = (priv_t *)ft->priv;
/* FIXME: We assume int == sox_sample_t here */
return (size_t)sf->sf_write_int(sf->sf_file, (int *)buf, (sf_count_t)len);
}
/*
* Close file for libsndfile (this doesn't close the file handle)
*/
static int stopwrite(sox_format_t * ft)
{
priv_t * sf = (priv_t *)ft->priv;
sf->sf_stop(sf->sf_file);
drain_log_buffer(ft);
sf->sf_close(sf->sf_file);
LSX_DLLIBRARY_CLOSE(sf, sndfile_dl);
return SOX_SUCCESS;
}
static int seek(sox_format_t * ft, uint64_t offset)
{
priv_t * sf = (priv_t *)ft->priv;
sf->sf_seek(sf->sf_file, (sf_count_t)(offset / ft->signal.channels), SEEK_CUR);
return SOX_SUCCESS;
}
LSX_FORMAT_HANDLER(sndfile)
{
static char const * const names[] = {
"sndfile", /* Special type to force use of sndfile for the following: */
/* LSF implementation of formats built in to SoX: */
/* "aif", */
/* "au", */
/* "gsm", */
/* "nist", */
/* "raw", */
/* "sf", "ircam", */
/* "snd", */
/* "svx", */
/* "voc", */
/* "vox", */
/* "wav", */
/* LSF wrappers of formats already wrapped in SoX: */
/* "flac", */
"sds", /* ?? */
NULL
};
static unsigned const write_encodings[] = {
SOX_ENCODING_SIGN2, 16, 24, 32, 8, 0,
SOX_ENCODING_UNSIGNED, 8, 0,
SOX_ENCODING_FLOAT, 32, 64, 0,
SOX_ENCODING_ALAW, 8, 0,
SOX_ENCODING_ULAW, 8, 0,
SOX_ENCODING_IMA_ADPCM, 4, 0,
SOX_ENCODING_MS_ADPCM, 4, 0,
SOX_ENCODING_OKI_ADPCM, 4, 0,
SOX_ENCODING_GSM, 0,
0};
static sox_format_handler_t const format = {SOX_LIB_VERSION_CODE,
"Pseudo format to use libsndfile", names, 0,
startread, read_samples, stopread,
startwrite, write_samples, stopwrite,
seek, write_encodings, NULL, sizeof(priv_t)
};
return &format;
}

@ -1,246 +0,0 @@
/*
* libsndio sound handler
*
* Copyright (c) 2009 Alexandre Ratchov <alex@caoua.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include "sox_i.h"
#include <string.h>
#include <sndio.h>
struct sndio_priv {
struct sio_hdl *hdl; /* handle to speak to libsndio */
struct sio_par par; /* current device parameters */
#define SNDIO_BUFSZ 0x1000
unsigned char buf[SNDIO_BUFSZ]; /* temp buffer for converions */
};
/*
* convert ``count'' samples from sox encoding to sndio encoding
*/
static void encode(struct sio_par *par,
sox_sample_t const *idata, unsigned char *odata, unsigned count)
{
int obnext, osnext, s, osigbit;
unsigned oshift, obps, i;
obps = par->bps;
osigbit = par->sig ? 0 : 1 << (par->bits - 1);
oshift = 32 - (par->msb ? par->bps * 8 : par->bits);
if (par->le) {
obnext = 1;
osnext = 0;
} else {
odata += par->bps - 1;
obnext = -1;
osnext = 2 * par->bps;
}
for (; count > 0; count--) {
s = (*idata++ >> oshift) ^ osigbit;
for (i = obps; i > 0; i--) {
*odata = (unsigned char)s;
s >>= 8;
odata += obnext;
}
odata += osnext;
}
}
/*
* convert ``count'' samples from sndio encoding to sox encoding
*/
static void decode(struct sio_par *par,
unsigned char *idata, sox_sample_t *odata, unsigned count)
{
unsigned ishift, ibps, i;
int s = 0xdeadbeef, ibnext, isnext, isigbit;
ibps = par->bps;
isigbit = par->sig ? 0 : 1 << (par->bits - 1);
ishift = 32 - (par->msb ? par->bps * 8 : par->bits);
if (par->le) {
idata += par->bps - 1;
ibnext = -1;
isnext = 2 * par->bps;
} else {
ibnext = 1;
isnext = 0;
}
for (; count > 0; count--) {
for (i = ibps; i > 0; i--) {
s <<= 8;
s |= *idata;
idata += ibnext;
}
idata += isnext;
*odata++ = (s ^ isigbit) << ishift;
}
}
static int startany(sox_format_t *ft, unsigned mode)
{
struct sndio_priv *p = (struct sndio_priv *)ft->priv;
struct sio_par reqpar;
char *device;
device = ft->filename;
if (strcmp("default", device) == 0)
device = NULL;
p->hdl = sio_open(device, mode, 0);
if (p->hdl == NULL)
return SOX_EOF;
/*
* set specified parameters, leaving others to the defaults
*/
sio_initpar(&reqpar);
if (ft->signal.rate > 0)
reqpar.rate = ft->signal.rate;
if (ft->signal.channels > 0) {
if (mode == SIO_PLAY)
reqpar.pchan = ft->signal.channels;
else
reqpar.rchan = ft->signal.channels;
}
switch (ft->encoding.encoding) {
case SOX_ENCODING_SIGN2:
reqpar.sig = 1;
break;
case SOX_ENCODING_UNSIGNED:
reqpar.sig = 0;
break;
default:
break; /* use device default */
}
if (ft->encoding.bits_per_sample > 0)
reqpar.bits = ft->encoding.bits_per_sample;
else if (ft->signal.precision > 0)
reqpar.bits = ft->signal.precision;
else
reqpar.bits = SOX_DEFAULT_PRECISION;
reqpar.bps = (reqpar.bits + 7) / 8;
reqpar.msb = 1;
if (ft->encoding.reverse_bytes != sox_option_default) {
reqpar.le = SIO_LE_NATIVE;
if (ft->encoding.reverse_bytes)
reqpar.le = !reqpar.le;
}
if (!sio_setpar(p->hdl, &reqpar) ||
!sio_getpar(p->hdl, &p->par))
goto failed;
ft->signal.channels = (mode == SIO_PLAY) ? p->par.pchan : p->par.rchan;
ft->signal.precision = p->par.bits;
ft->signal.rate = p->par.rate;
ft->encoding.encoding = p->par.sig ? SOX_ENCODING_SIGN2 : SOX_ENCODING_UNSIGNED;
ft->encoding.bits_per_sample = p->par.bps * 8;
ft->encoding.reverse_bytes = SIO_LE_NATIVE ? !p->par.le : p->par.le;
ft->encoding.reverse_nibbles = sox_option_no;
ft->encoding.reverse_bits = sox_option_no;
if (!sio_start(p->hdl))
goto failed;
return SOX_SUCCESS;
failed:
sio_close(p->hdl);
return SOX_EOF;
}
static int stopany(sox_format_t *ft)
{
sio_close(((struct sndio_priv *)ft->priv)->hdl);
return SOX_SUCCESS;
}
static int startread(sox_format_t *ft)
{
return startany(ft, SIO_REC);
}
static int startwrite(sox_format_t *ft)
{
return startany(ft, SIO_PLAY);
}
static size_t readsamples(sox_format_t *ft, sox_sample_t *buf, size_t len)
{
struct sndio_priv *p = (struct sndio_priv *)ft->priv;
unsigned char partial[4];
unsigned cpb, cc, pc;
size_t todo, n;
pc = 0;
todo = len * p->par.bps;
cpb = SNDIO_BUFSZ - (SNDIO_BUFSZ % p->par.bps);
while (todo > 0) {
memcpy(p->buf, partial, (size_t)pc);
cc = cpb - pc;
if (cc > todo)
cc = todo;
n = sio_read(p->hdl, p->buf + pc, (size_t)cc);
if (n == 0 && sio_eof(p->hdl))
break;
n += pc;
pc = n % p->par.bps;
n -= pc;
memcpy(partial, p->buf + n, (size_t)pc);
decode(&p->par, p->buf, buf, (unsigned)(n / p->par.bps));
buf += n / p->par.bps;
todo -= n;
}
return len - todo / p->par.bps;
}
static size_t writesamples(sox_format_t *ft, const sox_sample_t *buf, size_t len)
{
struct sndio_priv *p = (struct sndio_priv *)ft->priv;
unsigned sc, spb;
size_t n, todo;
todo = len;
spb = SNDIO_BUFSZ / p->par.bps;
while (todo > 0) {
sc = spb;
if (sc > todo)
sc = todo;
encode(&p->par, buf, p->buf, sc);
n = sio_write(p->hdl, p->buf, (size_t)(sc * p->par.bps));
if (n == 0 && sio_eof(p->hdl))
break;
n /= p->par.bps;
todo -= n;
buf += n;
}
return len - todo;
}
LSX_FORMAT_HANDLER(sndio)
{
static char const * const names[] = {"sndio", NULL};
static unsigned const write_encodings[] = {
SOX_ENCODING_SIGN2, 32, 24, 16, 8, 0,
SOX_ENCODING_UNSIGNED, 32, 24, 16, 8, 0,
0
};
static sox_format_handler_t const handler = {
SOX_LIB_VERSION_CODE,
"libsndio device driver",
names,
SOX_FILE_DEVICE | SOX_FILE_NOSTDIO,
startread, readsamples, stopany,
startwrite, writesamples, stopany,
NULL, write_encodings, NULL,
sizeof(struct sndio_priv)
};
return &handler;
}

@ -1,108 +0,0 @@
/* libSoX file format: SoX native (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>
static char const magic[2][4] = {".SoX", "XoS."};
#define FIXED_HDR (4 + 8 + 8 + 4 + 4) /* Without magic */
static int startread(sox_format_t * ft)
{
char magic_[sizeof(magic[0])];
uint32_t headers_bytes, num_channels, comments_bytes;
uint64_t num_samples;
double rate;
if (lsx_readdw(ft, (uint32_t *)&magic_))
return SOX_EOF;
if (memcmp(magic[MACHINE_IS_BIGENDIAN], magic_, sizeof(magic_))) {
if (memcmp(magic[MACHINE_IS_LITTLEENDIAN], magic_, sizeof(magic_))) {
lsx_fail_errno(ft, SOX_EHDR, "can't find sox file format identifier");
return SOX_EOF;
}
ft->encoding.reverse_bytes = !ft->encoding.reverse_bytes;
lsx_report("file is opposite endian");
}
if (lsx_readdw(ft, &headers_bytes) ||
lsx_readqw(ft, &num_samples) ||
lsx_readdf(ft, &rate) ||
lsx_readdw(ft, &num_channels) ||
lsx_readdw(ft, &comments_bytes))
return SOX_EOF;
if (((headers_bytes + 4) & 7) ||
comments_bytes > 0x40000000 || /* max 1 GB */
headers_bytes < FIXED_HDR + comments_bytes ||
(num_channels > 65535)) /* Reserve top 16 bits */ {
lsx_fail_errno(ft, SOX_EHDR, "invalid sox file format header");
return SOX_EOF;
}
if (comments_bytes) {
char * buf = lsx_calloc(1, (size_t)comments_bytes + 1); /* ensure nul-terminated */
if (lsx_readchars(ft, buf, (size_t)comments_bytes) != SOX_SUCCESS) {
free(buf);
return SOX_EOF;
}
sox_append_comments(&ft->oob.comments, buf);
free(buf);
}
/* Consume any bytes after the comments and before the start of the audio
* block. These may include comment padding up to a multiple of 8 bytes,
* and further header information that might be defined in future. */
lsx_seeki(ft, (off_t)(headers_bytes - FIXED_HDR - comments_bytes), SEEK_CUR);
return lsx_check_read_params(
ft, num_channels, rate, SOX_ENCODING_SIGN2, 32, num_samples, sox_true);
}
static int write_header(sox_format_t * ft)
{
char * comments = lsx_cat_comments(ft->oob.comments);
size_t comments_len = strlen(comments);
size_t comments_bytes = (comments_len + 7) & ~7u; /* Multiple of 8 bytes */
uint64_t size = ft->olength? ft->olength : ft->signal.length;
int error;
uint32_t header;
memcpy(&header, magic[MACHINE_IS_BIGENDIAN], sizeof(header));
error = 0
||lsx_writedw(ft, header)
||lsx_writedw(ft, FIXED_HDR + (unsigned)comments_bytes)
||lsx_writeqw(ft, size)
||lsx_writedf(ft, ft->signal.rate)
||lsx_writedw(ft, ft->signal.channels)
||lsx_writedw(ft, (unsigned)comments_len)
||lsx_writechars(ft, comments, comments_len)
||lsx_padbytes(ft, comments_bytes - comments_len);
free(comments);
return error? SOX_EOF: SOX_SUCCESS;
}
LSX_FORMAT_HANDLER(sox)
{
static char const * const names[] = {"sox", NULL};
static unsigned const write_encodings[] = {SOX_ENCODING_SIGN2, 32, 0, 0};
static sox_format_handler_t const handler = {SOX_LIB_VERSION_CODE,
"SoX native intermediate format", names, SOX_FILE_REWIND,
startread, lsx_rawread, NULL, write_header, lsx_rawwrite, NULL,
lsx_rawseek, write_encodings, NULL, 0
};
return &handler;
}

File diff suppressed because it is too large Load Diff

@ -1,349 +0,0 @@
/* libSoX effect: SpeexDsp effect to apply processing from libspeexdsp.
*
* Copyright 1999-2009 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"
#ifdef HAVE_SPEEXDSP
#include <speex/speex_types.h>
#include <speex/speex_preprocess.h>
/* Private data for effect */
typedef struct speexdsp_priv_t {
size_t buffer_end; /* Index of the end of the buffer. */
size_t buffer_ipos; /* Index for the next input sample. */
size_t buffer_opos; /* Index of the next sample that has not been drained. */
int16_t* buffer; /* Work buffer. */
SpeexPreprocessState* sps;/* DSP state. */
size_t agc; /* Param: Automatic Gain Control target volume level: 0 to disable, or 1-100 (target volume). */
size_t denoise; /* Param: Denoise: 0 to disable, or maximum noise attenuation in dB. */
size_t dereverb; /* Param: Dereverb: 0 to disable, 1 to enable. */
size_t frames_per_second; /* Param: Used to compute buffer size from sample rate. */
size_t samples_per_frame; /* Param: Used to compute buffer size directly. Default is to use frames_per_second instead. */
} priv_t;
static int get_param(
int* pArgc,
char*** pArgv,
size_t* pParam,
size_t default_val,
size_t min_valid,
size_t max_valid)
{
*pParam = default_val;
if (*pArgc > 1 && (*pArgv)[1][0] != '-')
{
char* arg_end;
*pParam = strtoul((*pArgv)[1], &arg_end, 0);
if (!arg_end || arg_end[0] || *pParam < min_valid || max_valid <= *pParam)
return 0;
--*pArgc;
++*pArgv;
}
return 1;
}
/*
* Process command-line options but don't do other
* initialization now: effp->in_signal & effp->out_signal are not
* yet filled in.
*/
static int getopts(sox_effect_t* effp, int argc, char** argv)
{
priv_t* p = (priv_t*)effp->priv;
const size_t agcDefault = 100;
const size_t denoiseDefault = 15;
const size_t fpsDefault = 50;
for (argc--, argv++; argc; argc--, argv++)
{
if (!strcasecmp("-agc", argv[0]))
{
/* AGC level argument is optional. If not specified, it defaults to agcDefault.
If specified, it must be from 0 to 100. */
if (!get_param(&argc, &argv, &p->agc, agcDefault, 0, 100))
{
lsx_fail("Invalid argument \"%s\" to -agc parameter - expected number from 0 to 100.", argv[1]);
return lsx_usage(effp);
}
}
else if (!strcasecmp("-denoise", argv[0]))
{
/* Denoise level argument is optional. If not specified, it defaults to denoiseDefault.
If specified, it must be from 0 to 100. */
if (!get_param(&argc, &argv, &p->denoise, denoiseDefault, 0, 100))
{
lsx_fail("Invalid argument \"%s\" to -denoise parameter - expected number from 0 to 100.", argv[1]);
return lsx_usage(effp);
}
}
else if (!strcasecmp("-dereverb", argv[0]))
{
p->dereverb = 1;
}
else if (!strcasecmp("-spf", argv[0]))
{
/* If samples_per_frame option is given, argument is required and must be
greater than 0. */
if (!get_param(&argc, &argv, &p->samples_per_frame, 0, 1, 1000000000) || !p->samples_per_frame)
{
lsx_fail("Invalid argument \"%s\" to -spf parameter - expected positive number.", argv[1]);
return lsx_usage(effp);
}
}
else if (!strcasecmp("-fps", argv[0]))
{
/* If frames_per_second option is given, argument is required and must be
from 1 to 100. This will be used later to compute samples_per_frame once
we know the sample rate). */
if (!get_param(&argc, &argv, &p->frames_per_second, 0, 1, 100) || !p->frames_per_second)
{
lsx_fail("Invalid argument \"%s\" to -fps parameter - expected number from 1 to 100.", argv[1]);
return lsx_usage(effp);
}
}
else
{
lsx_fail("Invalid parameter \"%s\".", argv[0]);
return lsx_usage(effp);
}
}
if (!p->frames_per_second)
p->frames_per_second = fpsDefault;
if (!p->agc && !p->denoise && !p->dereverb)
{
lsx_report("No features specified. Enabling default settings \"-agc %u -denoise %u\".", agcDefault, denoiseDefault);
p->agc = agcDefault;
p->denoise = denoiseDefault;
}
return SOX_SUCCESS;
}
/*
* Do anything required when you stop reading samples.
*/
static int stop(sox_effect_t* effp)
{
priv_t* p = (priv_t*)effp->priv;
if (p->sps)
{
speex_preprocess_state_destroy(p->sps);
p->sps = NULL;
}
if (p->buffer)
{
free(p->buffer);
p->buffer = NULL;
}
return SOX_SUCCESS;
}
/*
* Prepare processing.
* Do all initializations.
*/
static int start(sox_effect_t* effp)
{
priv_t* p = (priv_t*)effp->priv;
int result = SOX_SUCCESS;
spx_int32_t int_val;
float float_val;
if (p->samples_per_frame)
{
p->buffer_end = p->samples_per_frame;
}
else
{
p->buffer_end = effp->in_signal.rate / p->frames_per_second;
if (!p->buffer_end)
{
lsx_fail("frames_per_second too large for the current sample rate.");
return SOX_EOF;
}
}
p->buffer_opos = p->buffer_end;
effp->out_signal.precision = 16;
p->buffer = lsx_malloc(p->buffer_end * sizeof(p->buffer[0]));
if (!p->buffer)
{
result = SOX_ENOMEM;
goto Done;
}
p->sps = speex_preprocess_state_init((int)p->buffer_end, (int)(effp->in_signal.rate + .5));
if (!p->sps)
{
lsx_fail("Failed to initialize preprocessor DSP.");
result = SOX_EOF;
goto Done;
}
int_val = p->agc ? 1 : 2;
speex_preprocess_ctl(p->sps, SPEEX_PREPROCESS_SET_AGC, &int_val);
if (p->agc)
{
float_val = p->agc * 327.68f;
speex_preprocess_ctl(p->sps, SPEEX_PREPROCESS_SET_AGC_LEVEL, &float_val);
}
int_val = p->denoise ? 1 : 2;
speex_preprocess_ctl(p->sps, SPEEX_PREPROCESS_SET_DENOISE, &int_val);
if (p->denoise)
{
int_val = -(spx_int32_t)p->denoise;
speex_preprocess_ctl(p->sps, SPEEX_PREPROCESS_SET_NOISE_SUPPRESS, &int_val);
}
int_val = p->dereverb ? 1 : 2;
speex_preprocess_ctl(p->sps, SPEEX_PREPROCESS_SET_DEREVERB, &int_val);
Done:
if (result != SOX_SUCCESS)
stop(effp);
return result;
}
/*
* Process up to *isamp samples from ibuf and produce up to *osamp samples
* in obuf. Write back the actual numbers of samples to *isamp and *osamp.
* Return SOX_SUCCESS or, if error occurs, SOX_EOF.
*/
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 ibuf_pos = 0;
size_t ibuf_end = *isamp;
size_t obuf_pos = 0;
size_t obuf_end = *osamp;
size_t end_pos;
SOX_SAMPLE_LOCALS;
for (;;)
{
/* Write any processed data in working buffer to the output buffer. */
end_pos = obuf_pos + min(p->buffer_end - p->buffer_opos, obuf_end - obuf_pos);
for (; obuf_pos < end_pos; obuf_pos++, p->buffer_opos++)
obuf[obuf_pos] = SOX_SIGNED_16BIT_TO_SAMPLE(p->buffer[p->buffer_opos], dummy);
if (p->buffer_opos != p->buffer_end)
break; /* Output buffer is full and we still have more processed data. */
/* Fill working buffer from input buffer. */
end_pos = ibuf_pos + min(p->buffer_end - p->buffer_ipos, ibuf_end - ibuf_pos);
for (; ibuf_pos < end_pos; ibuf_pos++, p->buffer_ipos++)
p->buffer[p->buffer_ipos] = SOX_SAMPLE_TO_SIGNED_16BIT(ibuf[ibuf_pos], effp->clips);
if (p->buffer_ipos != p->buffer_end)
break; /* Working buffer is not full and there is no more input data. */
speex_preprocess_run(p->sps, p->buffer);
p->buffer_ipos = 0;
p->buffer_opos = 0;
}
*isamp = ibuf_pos;
*osamp = obuf_pos;
return SOX_SUCCESS;
}
/*
* Drain out remaining samples if the effect generates any.
*/
static int drain(sox_effect_t* effp, sox_sample_t* obuf, size_t* osamp)
{
priv_t* p = (priv_t*)effp->priv;
size_t obuf_pos = 0;
size_t obuf_end = *osamp;
size_t i;
size_t end_pos;
/* Input that hasn't been processed yet? */
if (p->buffer_ipos != 0)
{
/* DSP only works on full frames, so fill the remaining space with 0s. */
for (i = p->buffer_ipos; i < p->buffer_end; i++)
p->buffer[i] = 0;
speex_preprocess_run(p->sps, p->buffer);
p->buffer_end = p->buffer_ipos;
p->buffer_ipos = 0;
p->buffer_opos = 0;
}
end_pos = obuf_pos + min(p->buffer_end - p->buffer_opos, obuf_end - obuf_pos);
for (; obuf_pos < end_pos; obuf_pos++, p->buffer_opos++)
obuf[obuf_pos] = SOX_SIGNED_16BIT_TO_SAMPLE(p->buffer[p->buffer_opos], dummy);
*osamp = obuf_pos;
return
p->buffer_opos != p->buffer_end
? SOX_SUCCESS
: SOX_EOF;
}
/*
* Function returning effect descriptor. This should be the only
* externally visible object.
*/
const sox_effect_handler_t* lsx_speexdsp_effect_fn(void)
{
/*
* Effect descriptor.
* If no specific processing is needed for any of
* the 6 functions, then the function above can be deleted
* and NULL used in place of the its name below.
*/
static sox_effect_handler_t descriptor = {
"speexdsp", 0, SOX_EFF_PREC | SOX_EFF_GAIN | SOX_EFF_ALPHA,
getopts, start, flow, drain, stop, NULL, sizeof(priv_t)
};
static char const * lines[] = {
"Uses the Speex DSP library to improve perceived sound quality.",
"If no options are specified, the -agc and -denoise features are enabled.",
"Options:",
"-agc [target_level] Enable automatic gain control, and optionally specify a",
" target volume level from 1-100 (default is 100).",
"-denoise [max_dB] Enable noise reduction, and optionally specify the max",
" attenuation (default is 15).",
"-dereverb Enable reverb reduction.",
"-fps frames_per_second Specify the number of frames per second from 1-100",
" (default is 20).",
"-spf samples_per_frame Specify the number of samples per frame. Default is to",
" use the -fps setting.",
};
static char * usage;
descriptor.usage = lsx_usage_lines(&usage, lines, array_length(lines));
return &descriptor;
}
#endif /* HAVE_SPEEXDSP */

@ -1,302 +0,0 @@
/* libSoX effect: splice audio Copyright (c) 2008-9 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"
static double difference(
const sox_sample_t * a, const sox_sample_t * b, size_t length)
{
double diff = 0;
size_t i = 0;
#define _ diff += sqr((double)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 best_overlap_position(sox_sample_t const * f1,
sox_sample_t const * f2, uint64_t overlap, uint64_t search, size_t channels)
{
size_t i, best_pos = 0;
double diff, least_diff = difference(f2, f1, (size_t) (channels * overlap));
for (i = 1; i < search; ++i) { /* linear search */
diff = difference(f2 + channels * i, f1, (size_t) (channels * overlap));
if (diff < least_diff)
least_diff = diff, best_pos = i;
}
return best_pos;
}
typedef struct {
enum {Cosine_2, Cosine_4, Triangular} fade_type;
unsigned nsplices; /* Number of splices requested */
struct {
char * str; /* Command-line argument to parse for this splice */
uint64_t overlap; /* Number of samples to overlap */
uint64_t search; /* Number of samples to search */
uint64_t start; /* Start splicing when in_pos equals this */
} * splices;
uint64_t in_pos; /* Number of samples read from the input stream */
unsigned splices_pos; /* Number of splices completed so far */
size_t buffer_pos; /* Number of samples through the current splice */
size_t max_buffer_size;
sox_sample_t * buffer;
unsigned state;
} priv_t;
static void splice(sox_effect_t * effp, const sox_sample_t * in1, const
sox_sample_t * in2, sox_sample_t * output, uint64_t overlap, size_t channels)
{
priv_t * p = (priv_t *)effp->priv;
size_t i, j, k = 0;
if (p->fade_type == Cosine_4) {
double fade_step = M_PI_2 / overlap;
for (i = 0; i < overlap; ++i) {
double fade_in = sin(i * fade_step);
double fade_out = cos(i * fade_step); /* constant RMS level (`power') */
for (j = 0; j < channels; ++j, ++k) {
double d = in1[k] * fade_out + in2[k] * fade_in;
output[k] = SOX_ROUND_CLIP_COUNT(d, effp->clips); /* Might clip */
}
}
}
else if (p->fade_type == Cosine_2) {
double fade_step = M_PI / overlap;
for (i = 0; i < overlap; ++i) {
double fade_in = .5 - .5 * cos(i * fade_step);
double fade_out = 1 - fade_in; /* constant peak level (`gain') */
for (j = 0; j < channels; ++j, ++k) {
double d = in1[k] * fade_out + in2[k] * fade_in;
output[k] = SOX_ROUND_CLIP_COUNT(d, effp->clips); /* Should not clip */
}
}
}
else /* Triangular */ {
double fade_step = 1. / overlap;
for (i = 0; i < overlap; ++i) {
double fade_in = fade_step * i;
double fade_out = 1 - fade_in; /* constant peak level (`gain') */
for (j = 0; j < channels; ++j, ++k) {
double d = in1[k] * fade_out + in2[k] * fade_in;
output[k] = SOX_ROUND_CLIP_COUNT(d, effp->clips); /* Should not clip */
}
}
}
}
static uint64_t do_splice(sox_effect_t * effp,
sox_sample_t * f, uint64_t overlap, uint64_t search, size_t channels)
{
uint64_t offset = search? best_overlap_position(
f, f + overlap * channels, overlap, search, channels) : 0;
splice(effp, f, f + (overlap + offset) * channels,
f + (overlap + offset) * channels, overlap, channels);
return overlap + offset;
}
static int parse(sox_effect_t * effp, char * * argv, sox_rate_t rate)
{
priv_t * p = (priv_t *)effp->priv;
char const * next;
size_t i, buffer_size;
uint64_t last_seen = 0;
const uint64_t in_length = argv ? 0 :
(effp->in_signal.length != SOX_UNKNOWN_LEN ?
effp->in_signal.length / effp->in_signal.channels : SOX_UNKNOWN_LEN);
p->max_buffer_size = 0;
for (i = 0; i < p->nsplices; ++i) {
if (argv) /* 1st parse only */
p->splices[i].str = lsx_strdup(argv[i]);
p->splices[i].overlap = rate * 0.01 + .5;
p->splices[i].search = p->fade_type == Cosine_4? 0 : p->splices[i].overlap;
next = lsx_parseposition(rate, p->splices[i].str,
argv ? NULL : &p->splices[i].start, last_seen, in_length, '=');
if (next == NULL) break;
last_seen = p->splices[i].start;
if (*next == ',') {
next = lsx_parsesamples(rate, next + 1, &p->splices[i].overlap, 't');
if (next == NULL) break;
p->splices[i].overlap *= 2;
if (*next == ',') {
next = lsx_parsesamples(rate, next + 1, &p->splices[i].search, 't');
if (next == NULL) break;
p->splices[i].search *= 2;
}
}
if (*next != '\0') break;
p->splices[i].overlap = max(p->splices[i].overlap + 4, 16);
p->splices[i].overlap &= ~7; /* Make divisible by 8 for loop optimisation */
if (!argv) {
if (i > 0 && p->splices[i].start <= p->splices[i-1].start) break;
if (p->splices[i].start < p->splices[i].overlap) break;
p->splices[i].start -= p->splices[i].overlap;
buffer_size = 2 * p->splices[i].overlap + p->splices[i].search;
p->max_buffer_size = max(p->max_buffer_size, buffer_size);
}
}
if (i < p->nsplices)
return lsx_usage(effp);
return SOX_SUCCESS;
}
static int create(sox_effect_t * effp, int argc, char * * argv)
{
priv_t * p = (priv_t *)effp->priv;
--argc, ++argv;
if (argc) {
if (!strcmp(*argv, "-t")) p->fade_type = Triangular, --argc, ++argv;
else if (!strcmp(*argv, "-q")) p->fade_type = Cosine_4 , --argc, ++argv;
else if (!strcmp(*argv, "-h")) p->fade_type = Cosine_2 , --argc, ++argv;
}
p->nsplices = argc;
p->splices = lsx_calloc(p->nsplices, sizeof(*p->splices));
return parse(effp, argv, 1e5); /* No rate yet; parse with dummy */
}
static int start(sox_effect_t * effp)
{
priv_t * p = (priv_t *)effp->priv;
unsigned i;
parse(effp, 0, effp->in_signal.rate); /* Re-parse now rate is known */
p->buffer = lsx_calloc(p->max_buffer_size * effp->in_signal.channels, sizeof(*p->buffer));
p->in_pos = p->buffer_pos = p->splices_pos = 0;
p->state = p->splices_pos != p->nsplices && p->in_pos == p->splices[p->splices_pos].start;
effp->out_signal.length = SOX_UNKNOWN_LEN; /* depends on input data */
for (i = 0; i < p->nsplices; ++i)
if (p->splices[i].overlap) {
if (p->fade_type == Cosine_4 && effp->in_signal.mult)
*effp->in_signal.mult *= pow(.5, .5);
return SOX_SUCCESS;
}
return SOX_EFF_NULL;
}
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, idone = 0, odone = 0;
*isamp /= effp->in_signal.channels;
*osamp /= effp->in_signal.channels;
while (sox_true) {
copying:
if (p->state == 0) {
for (; idone < *isamp && odone < *osamp; ++idone, ++odone, ++p->in_pos) {
if (p->splices_pos != p->nsplices && p->in_pos == p->splices[p->splices_pos].start) {
p->state = 1;
goto buffering;
}
for (c = 0; c < effp->in_signal.channels; ++c)
*obuf++ = *ibuf++;
}
break;
}
buffering:
if (p->state == 1) {
size_t buffer_size = (2 * p->splices[p->splices_pos].overlap + p->splices[p->splices_pos].search) * effp->in_signal.channels;
for (; idone < *isamp; ++idone, ++p->in_pos) {
if (p->buffer_pos == buffer_size) {
p->buffer_pos = do_splice(effp, p->buffer,
p->splices[p->splices_pos].overlap,
p->splices[p->splices_pos].search,
(size_t)effp->in_signal.channels) * effp->in_signal.channels;
p->state = 2;
goto flushing;
break;
}
for (c = 0; c < effp->in_signal.channels; ++c)
p->buffer[p->buffer_pos++] = *ibuf++;
}
break;
}
flushing:
if (p->state == 2) {
size_t buffer_size = (2 * p->splices[p->splices_pos].overlap + p->splices[p->splices_pos].search) * effp->in_signal.channels;
for (; odone < *osamp; ++odone) {
if (p->buffer_pos == buffer_size) {
p->buffer_pos = 0;
++p->splices_pos;
p->state = p->splices_pos != p->nsplices && p->in_pos == p->splices[p->splices_pos].start;
goto copying;
}
for (c = 0; c < effp->in_signal.channels; ++c)
*obuf++ = p->buffer[p->buffer_pos++];
}
break;
}
}
*isamp = idone * effp->in_signal.channels;
*osamp = odone * effp->in_signal.channels;
return SOX_SUCCESS;
}
static int drain(sox_effect_t * effp, sox_sample_t * obuf, size_t * osamp)
{
size_t isamp = 0;
return flow(effp, 0, obuf, &isamp, osamp);
}
static int stop(sox_effect_t * effp)
{
priv_t * p = (priv_t *)effp->priv;
if (p->splices_pos != p->nsplices)
lsx_warn("Input audio too short; splices not made: %u", p->nsplices - p->splices_pos);
free(p->buffer);
return SOX_SUCCESS;
}
static int lsx_kill(sox_effect_t * effp)
{
priv_t * p = (priv_t *)effp->priv;
unsigned i;
for (i = 0; i < p->nsplices; ++i)
free(p->splices[i].str);
free(p->splices);
return SOX_SUCCESS;
}
sox_effect_handler_t const * lsx_splice_effect_fn(void)
{
static sox_effect_handler_t handler = {
"splice", "[-h|-t|-q] {position[,excess[,leeway]]}"
"\n -h Half sine fade (default); constant gain (for correlated audio)"
"\n -t Triangular (linear) fade; constant gain (for correlated audio)"
"\n -q Quarter sine fade; constant power (for correlated audio e.g. x-fade)"
"\n position The length of part 1 (including the excess)"
"\n excess At the end of part 1 & the start of part2 (default 0.005)"
"\n leeway Before part2 (default 0.005; set to 0 for cross-fade)",
SOX_EFF_MCHAN | SOX_EFF_LENGTH,
create, start, flow, drain, stop, lsx_kill, sizeof(priv_t)
};
return &handler;
}

@ -1,336 +0,0 @@
/* libSoX statistics "effect" file.
*
* Compute various statistics on file and print them.
*
* Output is unmodified from input.
*
* July 5, 1991
* Copyright 1991 Lance Norskog And Sundry Contributors
* This source code is freely redistributable and may be used for
* any purpose. This copyright notice must be maintained.
* Lance Norskog And Sundry Contributors are not responsible for
* the consequences of using this software.
*/
#include "sox_i.h"
#include <string.h>
/* Private data for stat effect */
typedef struct {
double min, max, mid;
double asum;
double sum1, sum2; /* amplitudes */
double dmin, dmax;
double dsum1, dsum2; /* deltas */
double scale; /* scale-factor */
double last; /* previous sample */
uint64_t read; /* samples processed */
int volume;
int srms;
int fft;
unsigned long bin[4];
float *re_in;
float *re_out;
unsigned long fft_size;
unsigned long fft_offset;
} priv_t;
/*
* Process options
*/
static int sox_stat_getopts(sox_effect_t * effp, int argc, char **argv)
{
priv_t * stat = (priv_t *) effp->priv;
stat->scale = SOX_SAMPLE_MAX;
stat->volume = 0;
stat->srms = 0;
stat->fft = 0;
--argc, ++argv;
for (; argc > 0; argc--, argv++) {
if (!(strcmp(*argv, "-v")))
stat->volume = 1;
else if (!(strcmp(*argv, "-s"))) {
if (argc <= 1) {
lsx_fail("-s option: invalid argument");
return SOX_EOF;
}
argc--, argv++; /* Move to next argument. */
if (!sscanf(*argv, "%lf", &stat->scale)) {
lsx_fail("-s option: invalid argument");
return SOX_EOF;
}
} else if (!(strcmp(*argv, "-rms")))
stat->srms = 1;
else if (!(strcmp(*argv, "-freq")))
stat->fft = 1;
else if (!(strcmp(*argv, "-d")))
stat->volume = 2;
else {
lsx_fail("Summary effect: unknown option");
return SOX_EOF;
}
}
return SOX_SUCCESS;
}
/*
* Prepare processing.
*/
static int sox_stat_start(sox_effect_t * effp)
{
priv_t * stat = (priv_t *) effp->priv;
int i;
stat->min = stat->max = stat->mid = 0;
stat->asum = 0;
stat->sum1 = stat->sum2 = 0;
stat->dmin = stat->dmax = 0;
stat->dsum1 = stat->dsum2 = 0;
stat->last = 0;
stat->read = 0;
for (i = 0; i < 4; i++)
stat->bin[i] = 0;
stat->fft_size = 4096;
stat->re_in = stat->re_out = NULL;
if (stat->fft) {
stat->fft_offset = 0;
stat->re_in = lsx_malloc(sizeof(float) * stat->fft_size);
stat->re_out = lsx_malloc(sizeof(float) * (stat->fft_size / 2 + 1));
}
return SOX_SUCCESS;
}
/*
* Print power spectrum to given stream
*/
static void print_power_spectrum(unsigned samples, double rate, float *re_in, float *re_out)
{
float ffa = rate / samples;
unsigned i;
lsx_power_spectrum_f((int)samples, re_in, re_out);
for (i = 0; i < samples / 2; i++) /* FIXME: should be <= samples / 2 */
fprintf(stderr, "%f %f\n", ffa * i, re_out[i]);
}
/*
* Processed signed long samples from ibuf to obuf.
* Return number of samples processed.
*/
static int sox_stat_flow(sox_effect_t * effp, const sox_sample_t *ibuf, sox_sample_t *obuf,
size_t *isamp, size_t *osamp)
{
priv_t * stat = (priv_t *) effp->priv;
int done, x, len = min(*isamp, *osamp);
short count = 0;
if (len) {
if (stat->read == 0) /* 1st sample */
stat->min = stat->max = stat->mid = stat->last = (*ibuf)/stat->scale;
if (stat->fft) {
for (x = 0; x < len; x++) {
SOX_SAMPLE_LOCALS;
stat->re_in[stat->fft_offset++] = SOX_SAMPLE_TO_FLOAT_32BIT(ibuf[x], effp->clips);
if (stat->fft_offset >= stat->fft_size) {
stat->fft_offset = 0;
print_power_spectrum((unsigned) stat->fft_size, effp->in_signal.rate, stat->re_in, stat->re_out);
}
}
}
for (done = 0; done < len; done++) {
long lsamp = *ibuf++;
double delta, samp = (double)lsamp / stat->scale;
/* work in scaled levels for both sample and delta */
stat->bin[(lsamp >> 30) + 2]++;
*obuf++ = lsamp;
if (stat->volume == 2) {
fprintf(stderr,"%08lx ",lsamp);
if (count++ == 5) {
fprintf(stderr,"\n");
count = 0;
}
}
/* update min/max */
if (stat->min > samp)
stat->min = samp;
else if (stat->max < samp)
stat->max = samp;
stat->mid = stat->min / 2 + stat->max / 2;
stat->sum1 += samp;
stat->sum2 += samp*samp;
stat->asum += fabs(samp);
delta = fabs(samp - stat->last);
if (delta < stat->dmin)
stat->dmin = delta;
else if (delta > stat->dmax)
stat->dmax = delta;
stat->dsum1 += delta;
stat->dsum2 += delta*delta;
stat->last = samp;
}
stat->read += len;
}
*isamp = *osamp = len;
/* Process all samples */
return SOX_SUCCESS;
}
/*
* Process tail of input samples.
*/
static int sox_stat_drain(sox_effect_t * effp, sox_sample_t *obuf UNUSED, size_t *osamp)
{
priv_t * stat = (priv_t *) effp->priv;
/* When we run out of samples, then we need to pad buffer with
* zeros and then run FFT one last time to process any unprocessed
* samples.
*/
if (stat->fft && stat->fft_offset) {
unsigned int x;
for (x = stat->fft_offset; x < stat->fft_size; x++)
stat->re_in[x] = 0;
print_power_spectrum((unsigned) stat->fft_size, effp->in_signal.rate, stat->re_in, stat->re_out);
}
*osamp = 0;
return SOX_EOF;
}
/*
* Do anything required when you stop reading samples.
* Don't close input file!
*/
static int sox_stat_stop(sox_effect_t * effp)
{
priv_t * stat = (priv_t *) effp->priv;
double amp, scale, rms = 0, freq;
double x, ct;
ct = stat->read;
if (stat->srms) { /* adjust results to units of rms */
double f;
rms = sqrt(stat->sum2/ct);
f = 1.0/rms;
stat->max *= f;
stat->min *= f;
stat->mid *= f;
stat->asum *= f;
stat->sum1 *= f;
stat->sum2 *= f*f;
stat->dmax *= f;
stat->dmin *= f;
stat->dsum1 *= f;
stat->dsum2 *= f*f;
stat->scale *= rms;
}
scale = stat->scale;
amp = -stat->min;
if (amp < stat->max)
amp = stat->max;
/* Just print the volume adjustment */
if (stat->volume == 1 && amp > 0) {
fprintf(stderr, "%.3f\n", SOX_SAMPLE_MAX/(amp*scale));
return SOX_SUCCESS;
}
if (stat->volume == 2)
fprintf(stderr, "\n\n");
/* print out the info */
fprintf(stderr, "Samples read: %12" PRIu64 "\n", stat->read);
fprintf(stderr, "Length (seconds): %12.6f\n", (double)stat->read/effp->in_signal.rate/effp->in_signal.channels);
if (stat->srms)
fprintf(stderr, "Scaled by rms: %12.6f\n", rms);
else
fprintf(stderr, "Scaled by: %12.1f\n", scale);
fprintf(stderr, "Maximum amplitude: %12.6f\n", stat->max);
fprintf(stderr, "Minimum amplitude: %12.6f\n", stat->min);
fprintf(stderr, "Midline amplitude: %12.6f\n", stat->mid);
fprintf(stderr, "Mean norm: %12.6f\n", stat->asum/ct);
fprintf(stderr, "Mean amplitude: %12.6f\n", stat->sum1/ct);
fprintf(stderr, "RMS amplitude: %12.6f\n", sqrt(stat->sum2/ct));
fprintf(stderr, "Maximum delta: %12.6f\n", stat->dmax);
fprintf(stderr, "Minimum delta: %12.6f\n", stat->dmin);
fprintf(stderr, "Mean delta: %12.6f\n", stat->dsum1/(ct-1));
fprintf(stderr, "RMS delta: %12.6f\n", sqrt(stat->dsum2/(ct-1)));
freq = sqrt(stat->dsum2/stat->sum2)*effp->in_signal.rate/(M_PI*2);
fprintf(stderr, "Rough frequency: %12d\n", (int)freq);
if (amp>0)
fprintf(stderr, "Volume adjustment: %12.3f\n", SOX_SAMPLE_MAX/(amp*scale));
if (stat->bin[2] == 0 && stat->bin[3] == 0)
fprintf(stderr, "\nProbably text, not sound\n");
else {
x = (float)(stat->bin[0] + stat->bin[3]) / (float)(stat->bin[1] + stat->bin[2]);
if (x >= 3.0) { /* use opposite encoding */
if (effp->in_encoding->encoding == SOX_ENCODING_UNSIGNED)
fprintf(stderr,"\nTry: -t raw -e signed-integer -b 8 \n");
else
fprintf(stderr,"\nTry: -t raw -e unsigned-integer -b 8 \n");
} else if (x <= 1.0 / 3.0)
; /* correctly decoded */
else if (x >= 0.5 && x <= 2.0) { /* use ULAW */
if (effp->in_encoding->encoding == SOX_ENCODING_ULAW)
fprintf(stderr,"\nTry: -t raw -e unsigned-integer -b 8 \n");
else
fprintf(stderr,"\nTry: -t raw -e mu-law -b 8 \n");
} else
fprintf(stderr, "\nCan't guess the type\n");
}
/* Release FFT memory */
free(stat->re_in);
free(stat->re_out);
return SOX_SUCCESS;
}
static sox_effect_handler_t sox_stat_effect = {
"stat",
"[ -s N ] [ -rms ] [-freq] [ -v ] [ -d ]",
SOX_EFF_MCHAN | SOX_EFF_MODIFY,
sox_stat_getopts,
sox_stat_start,
sox_stat_flow,
sox_stat_drain,
sox_stat_stop,
NULL, sizeof(priv_t)
};
const sox_effect_handler_t *lsx_stat_effect_fn(void)
{
return &sox_stat_effect;
}

@ -1,298 +0,0 @@
/* libSoX effect: stats (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 <ctype.h>
#include <string.h>
typedef struct {
int scale_bits, hex_bits;
double time_constant, scale;
double last, sigma_x, sigma_x2, avg_sigma_x2, min_sigma_x2, max_sigma_x2;
double min, max, mult, min_run, min_runs, max_run, max_runs;
off_t num_samples, tc_samples, min_count, max_count;
uint32_t mask;
} priv_t;
static int getopts(sox_effect_t * effp, int argc, char **argv)
{
priv_t * p = (priv_t *)effp->priv;
int c;
lsx_getopt_t optstate;
lsx_getopt_init(argc, argv, "+x:b:w:s:", NULL, lsx_getopt_flag_none, 1, &optstate);
p->time_constant = .05;
p->scale = 1;
while ((c = lsx_getopt(&optstate)) != -1) switch (c) {
GETOPT_NUMERIC(optstate, 'x', hex_bits , 2 , 32)
GETOPT_NUMERIC(optstate, 'b', scale_bits , 2 , 32)
GETOPT_NUMERIC(optstate, 'w', time_constant , .01 , 10)
GETOPT_NUMERIC(optstate, 's', scale , -99, 99)
default: lsx_fail("invalid option `-%c'", optstate.opt); return lsx_usage(effp);
}
if (p->hex_bits)
p->scale_bits = p->hex_bits;
return optstate.ind != argc? lsx_usage(effp) : SOX_SUCCESS;
}
static int start(sox_effect_t * effp)
{
priv_t * p = (priv_t *)effp->priv;
p->last = 0;
p->mult = exp((-1 / p->time_constant / effp->in_signal.rate));
p->tc_samples = 5 * p->time_constant * effp->in_signal.rate + .5;
p->sigma_x = p->sigma_x2 = p->avg_sigma_x2 = p->max_sigma_x2 = 0;
p->min = p->min_sigma_x2 = 2;
p->max = -p->min;
p->num_samples = 0;
p->mask = 0;
return SOX_SUCCESS;
}
static int flow(sox_effect_t * effp, const sox_sample_t * ibuf,
sox_sample_t * obuf, size_t * ilen, size_t * olen)
{
priv_t * p = (priv_t *)effp->priv;
size_t len = *ilen = *olen = min(*ilen, *olen);
memcpy(obuf, ibuf, len * sizeof(*obuf));
for (; len--; ++ibuf, ++p->num_samples) {
double d = SOX_SAMPLE_TO_FLOAT_64BIT(*ibuf,);
if (d < p->min)
p->min = d, p->min_count = 1, p->min_run = 1, p->min_runs = 0;
else if (d == p->min) {
++p->min_count;
p->min_run = d == p->last? p->min_run + 1 : 1;
}
else if (p->last == p->min)
p->min_runs += sqr(p->min_run);
if (d > p->max)
p->max = d, p->max_count = 1, p->max_run = 1, p->max_runs = 0;
else if (d == p->max) {
++p->max_count;
p->max_run = d == p->last? p->max_run + 1 : 1;
}
else if (p->last == p->max)
p->max_runs += sqr(p->max_run);
p->sigma_x += d;
p->sigma_x2 += sqr(d);
p->avg_sigma_x2 = p->avg_sigma_x2 * p->mult + (1 - p->mult) * sqr(d);
if (p->num_samples >= p->tc_samples) {
if (p->avg_sigma_x2 > p->max_sigma_x2)
p->max_sigma_x2 = p->avg_sigma_x2;
if (p->avg_sigma_x2 < p->min_sigma_x2)
p->min_sigma_x2 = p->avg_sigma_x2;
}
p->last = d;
p->mask |= *ibuf;
}
return SOX_SUCCESS;
}
static int drain(sox_effect_t * effp, sox_sample_t * obuf, size_t * olen)
{
priv_t * p = (priv_t *)effp->priv;
if (p->last == p->min)
p->min_runs += sqr(p->min_run);
if (p->last == p->max)
p->max_runs += sqr(p->max_run);
(void)obuf, *olen = 0;
return SOX_SUCCESS;
}
static unsigned bit_depth(uint32_t mask, double min, double max, unsigned * x)
{
SOX_SAMPLE_LOCALS;
unsigned result = 32, dummy = 0;
for (; result && !(mask & 1); --result, mask >>= 1);
if (x)
*x = result;
min = -fmax(fabs(min), fabs(max));
mask = SOX_FLOAT_64BIT_TO_SAMPLE(min, dummy) << 1;
for (; result && (mask & SOX_SAMPLE_MIN); --result, mask <<= 1);
return result;
}
static void output(priv_t const * p, double x)
{
if (p->scale_bits) {
unsigned mult = 1 << (p->scale_bits - 1);
int i;
x = floor(x * mult + .5);
i = min(x, mult - 1.);
if (p->hex_bits)
if (x < 0) {
char buf[30];
sprintf(buf, "%x", -i);
fprintf(stderr, " %*c%s", 9 - (int)strlen(buf), '-', buf);
}
else fprintf(stderr, " %9x", i);
else fprintf(stderr, " %9i", i);
}
else fprintf(stderr, " %9.*f", fabs(p->scale) < 10 ? 6 : 5, p->scale * x);
}
static int stop(sox_effect_t * effp)
{
priv_t * p = (priv_t *)effp->priv;
if (!effp->flow) {
double min_runs = 0, max_count = 0, min = 2, max = -2, max_sigma_x = 0, sigma_x = 0, sigma_x2 = 0, min_sigma_x2 = 2, max_sigma_x2 = 0, avg_peak = 0;
off_t num_samples = 0, min_count = 0, max_runs = 0;
uint32_t mask = 0;
unsigned b1, b2, i, n = effp->flows > 1 ? effp->flows : 0;
for (i = 0; i < effp->flows; ++i) {
priv_t * q = (priv_t *)(effp - effp->flow + i)->priv;
min = min(min, q->min);
max = max(max, q->max);
if (q->num_samples < q->tc_samples)
q->min_sigma_x2 = q->max_sigma_x2 = q->sigma_x2 / q->num_samples;
min_sigma_x2 = min(min_sigma_x2, q->min_sigma_x2);
max_sigma_x2 = max(max_sigma_x2, q->max_sigma_x2);
sigma_x += q->sigma_x;
sigma_x2 += q->sigma_x2;
num_samples += q->num_samples;
mask |= q->mask;
if (fabs(q->sigma_x) > fabs(max_sigma_x))
max_sigma_x = q->sigma_x;
min_count += q->min_count;
min_runs += q->min_runs;
max_count += q->max_count;
max_runs += q->max_runs;
avg_peak += max(-q->min, q->max);
}
avg_peak /= effp->flows;
if (!num_samples) {
lsx_warn("no audio");
return SOX_SUCCESS;
}
if (n == 2)
fprintf(stderr, " Overall Left Right\n");
else if (n) {
fprintf(stderr, " Overall");
for (i = 0; i < n; ++i)
fprintf(stderr, " Ch%-3i", i + 1);
fprintf(stderr, "\n");
}
fprintf(stderr, "DC offset ");
output(p, max_sigma_x / p->num_samples);
for (i = 0; i < n; ++i) {
priv_t * q = (priv_t *)(effp - effp->flow + i)->priv;
output(p, q->sigma_x / q->num_samples);
}
fprintf(stderr, "\nMin level ");
output(p, min);
for (i = 0; i < n; ++i) {
priv_t * q = (priv_t *)(effp - effp->flow + i)->priv;
output(p, q->min);
}
fprintf(stderr, "\nMax level ");
output(p, max);
for (i = 0; i < n; ++i) {
priv_t * q = (priv_t *)(effp - effp->flow + i)->priv;
output(p, q->max);
}
fprintf(stderr, "\nPk lev dB %10.2f", linear_to_dB(max(-min, max)));
for (i = 0; i < n; ++i) {
priv_t * q = (priv_t *)(effp - effp->flow + i)->priv;
fprintf(stderr, "%10.2f", linear_to_dB(max(-q->min, q->max)));
}
fprintf(stderr, "\nRMS lev dB%10.2f", linear_to_dB(sqrt(sigma_x2 / num_samples)));
for (i = 0; i < n; ++i) {
priv_t * q = (priv_t *)(effp - effp->flow + i)->priv;
fprintf(stderr, "%10.2f", linear_to_dB(sqrt(q->sigma_x2 / q->num_samples)));
}
fprintf(stderr, "\nRMS Pk dB %10.2f", linear_to_dB(sqrt(max_sigma_x2)));
for (i = 0; i < n; ++i) {
priv_t * q = (priv_t *)(effp - effp->flow + i)->priv;
fprintf(stderr, "%10.2f", linear_to_dB(sqrt(q->max_sigma_x2)));
}
fprintf(stderr, "\nRMS Tr dB ");
if (min_sigma_x2 != 1)
fprintf(stderr, "%10.2f", linear_to_dB(sqrt(min_sigma_x2)));
else fprintf(stderr, " -");
for (i = 0; i < n; ++i) {
priv_t * q = (priv_t *)(effp - effp->flow + i)->priv;
if (q->min_sigma_x2 != 1)
fprintf(stderr, "%10.2f", linear_to_dB(sqrt(q->min_sigma_x2)));
else fprintf(stderr, " -");
}
if (effp->flows > 1)
fprintf(stderr, "\nCrest factor -");
else fprintf(stderr, "\nCrest factor %7.2f", sigma_x2 ? avg_peak / sqrt(sigma_x2 / num_samples) : 1);
for (i = 0; i < n; ++i) {
priv_t * q = (priv_t *)(effp - effp->flow + i)->priv;
fprintf(stderr, "%10.2f", q->sigma_x2? max(-q->min, q->max) / sqrt(q->sigma_x2 / q->num_samples) : 1);
}
fprintf(stderr, "\nFlat factor%9.2f", linear_to_dB((min_runs + max_runs) / (min_count + max_count)));
for (i = 0; i < n; ++i) {
priv_t * q = (priv_t *)(effp - effp->flow + i)->priv;
fprintf(stderr, " %9.2f", linear_to_dB((q->min_runs + q->max_runs) / (q->min_count + q->max_count)));
}
fprintf(stderr, "\nPk count %9s", lsx_sigfigs3((min_count + max_count) / effp->flows));
for (i = 0; i < n; ++i) {
priv_t * q = (priv_t *)(effp - effp->flow + i)->priv;
fprintf(stderr, " %9s", lsx_sigfigs3((double)(q->min_count + q->max_count)));
}
b1 = bit_depth(mask, min, max, &b2);
fprintf(stderr, "\nBit-depth %2u/%-2u", b1, b2);
for (i = 0; i < n; ++i) {
priv_t * q = (priv_t *)(effp - effp->flow + i)->priv;
b1 = bit_depth(q->mask, q->min, q->max, &b2);
fprintf(stderr, " %2u/%-2u", b1, b2);
}
fprintf(stderr, "\nNum samples%9s", lsx_sigfigs3((double)p->num_samples));
fprintf(stderr, "\nLength s %9.3f", p->num_samples / effp->in_signal.rate);
fprintf(stderr, "\nScale max ");
output(p, 1.);
fprintf(stderr, "\nWindow s %9.3f", p->time_constant);
fprintf(stderr, "\n");
}
return SOX_SUCCESS;
}
sox_effect_handler_t const * lsx_stats_effect_fn(void)
{
static sox_effect_handler_t handler = {
"stats", "[-b bits|-x bits|-s scale] [-w window-time]", SOX_EFF_MODIFY,
getopts, start, flow, drain, stop, NULL, sizeof(priv_t)};
return &handler;
}

@ -1,326 +0,0 @@
/* libSoX Basic time stretcher.
* (c) march/april 2000 Fabien COELHO <fabien@coelho.net> for sox.
*
* cross fade samples so as to go slower or faster.
*
* The filter is based on 6 parameters:
* - stretch factor f
* - window size w
* - input step i
* output step o=f*i
* - steady state of window s, ss = s*w
*
* I decided of the default values of these parameters based
* on some small non extensive tests. maybe better defaults
* can be suggested.
*/
#include "sox_i.h"
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#define DEFAULT_SLOW_SHIFT_RATIO 0.8
#define DEFAULT_FAST_SHIFT_RATIO 1.0
#define DEFAULT_STRETCH_WINDOW 20.0 /* ms */
typedef enum { input_state, output_state } stretch_status_t;
typedef struct {
/* options
* FIXME: maybe shift could be allowed > 1.0 with factor < 1.0 ???
*/
double factor; /* strech factor. 1.0 means copy. */
double window; /* window in ms */
double shift; /* shift ratio wrt window. <1.0 */
double fading; /* fading ratio wrt window. <0.5 */
/* internal stuff */
stretch_status_t state; /* automaton status */
size_t segment; /* buffer size */
size_t index; /* next available element */
sox_sample_t *ibuf; /* input buffer */
size_t ishift; /* input shift */
size_t oindex; /* next evailable element */
double * obuf; /* output buffer */
size_t oshift; /* output shift */
size_t overlap; /* fading size */
double * fade_coefs; /* fading, 1.0 -> 0.0 */
} priv_t;
/*
* Process options
*/
static int getopts(sox_effect_t * effp, int argc, char **argv)
{
priv_t * p = (priv_t *) effp->priv;
--argc, ++argv;
/* default options */
p->factor = 1.0; /* default is no change */
p->window = DEFAULT_STRETCH_WINDOW;
if (argc > 0 && !sscanf(argv[0], "%lf", &p->factor)) {
lsx_fail("error while parsing factor");
return lsx_usage(effp);
}
if (argc > 1 && !sscanf(argv[1], "%lf", &p->window)) {
lsx_fail("error while parsing window size");
return lsx_usage(effp);
}
if (argc > 2) {
switch (argv[2][0]) {
case 'l':
case 'L':
break;
default:
lsx_fail("error while parsing fade type");
return lsx_usage(effp);
}
}
/* default shift depends whether we go slower or faster */
p->shift = (p->factor <= 1.0) ?
DEFAULT_FAST_SHIFT_RATIO: DEFAULT_SLOW_SHIFT_RATIO;
if (argc > 3 && !sscanf(argv[3], "%lf", &p->shift)) {
lsx_fail("error while parsing shift ratio");
return lsx_usage(effp);
}
if (p->shift > 1.0 || p->shift <= 0.0) {
lsx_fail("error with shift ratio value");
return lsx_usage(effp);
}
/* default fading stuff...
it makes sense for factor >= 0.5 */
if (p->factor < 1.0)
p->fading = 1.0 - (p->factor * p->shift);
else
p->fading = 1.0 - p->shift;
if (p->fading > 0.5)
p->fading = 0.5;
if (argc > 4 && !sscanf(argv[4], "%lf", &p->fading)) {
lsx_fail("error while parsing fading ratio");
return lsx_usage(effp);
}
if (p->fading > 0.5 || p->fading < 0.0) {
lsx_fail("error with fading ratio value");
return lsx_usage(effp);
}
return SOX_SUCCESS;
}
/*
* Start processing
*/
static int start(sox_effect_t * effp)
{
priv_t * p = (priv_t *)effp->priv;
size_t i;
if (p->factor == 1)
return SOX_EFF_NULL;
p->state = input_state;
p->segment = (int)(effp->out_signal.rate * 0.001 * p->window);
/* start in the middle of an input to avoid initial fading... */
p->index = p->segment / 2;
p->ibuf = lsx_malloc(p->segment * sizeof(sox_sample_t));
/* the shift ratio deal with the longest of ishift/oshift
hence ishift<=segment and oshift<=segment. */
if (p->factor < 1.0) {
p->ishift = p->shift * p->segment;
p->oshift = p->factor * p->ishift;
} else {
p->oshift = p->shift * p->segment;
p->ishift = p->oshift / p->factor;
}
assert(p->ishift <= p->segment);
assert(p->oshift <= p->segment);
p->oindex = p->index; /* start as synchronized */
p->obuf = lsx_malloc(p->segment * sizeof(double));
p->overlap = (int)(p->fading * p->segment);
p->fade_coefs = lsx_malloc(p->overlap * sizeof(double));
/* initialize buffers */
for (i = 0; i<p->segment; i++)
p->ibuf[i] = 0;
for (i = 0; i<p->segment; i++)
p->obuf[i] = 0.0;
if (p->overlap>1) {
double slope = 1.0 / (p->overlap - 1);
p->fade_coefs[0] = 1.0;
for (i = 1; i < p->overlap - 1; i++)
p->fade_coefs[i] = slope * (p->overlap - i - 1);
p->fade_coefs[p->overlap - 1] = 0.0;
} else if (p->overlap == 1)
p->fade_coefs[0] = 1.0;
lsx_debug("start: (factor=%g segment=%g shift=%g overlap=%g)\nstate=%d\n"
"segment=%" PRIuPTR "\nindex=%" PRIuPTR "\n"
"ishift=%" PRIuPTR "\noindex=%" PRIuPTR "\n"
"oshift=%" PRIuPTR "\noverlap=%" PRIuPTR,
p->factor, p->window, p->shift, p->fading, p->state,
p->segment, p->index, p->ishift, p->oindex, p->oshift, p->overlap);
effp->out_signal.length = SOX_UNKNOWN_LEN; /* TODO: calculate actual length */
return SOX_SUCCESS;
}
/* accumulates input ibuf to output obuf with fading fade_coefs */
static void combine(priv_t * p)
{
size_t i;
/* fade in */
for (i = 0; i < p->overlap; i++)
p->obuf[i] += p->fade_coefs[p->overlap - 1 - i] * p->ibuf[i];
/* steady state */
for (; i < p->segment - p->overlap; i++)
p->obuf[i] += p->ibuf[i];
/* fade out */
for (; i<p->segment; i++)
p->obuf[i] += p->fade_coefs[i - p->segment + p->overlap] * p->ibuf[i];
}
/*
* Processes flow.
*/
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 iindex = 0, oindex = 0;
size_t i;
while (iindex<*isamp && oindex<*osamp) {
if (p->state == input_state) {
size_t tocopy = min(*isamp-iindex,
p->segment-p->index);
memcpy(p->ibuf + p->index, ibuf + iindex, tocopy * sizeof(sox_sample_t));
iindex += tocopy;
p->index += tocopy;
if (p->index == p->segment) {
/* compute */
combine(p);
/* shift input */
for (i = 0; i + p->ishift < p->segment; i++)
p->ibuf[i] = p->ibuf[i+p->ishift];
p->index -= p->ishift;
/* switch to output state */
p->state = output_state;
}
}
if (p->state == output_state) {
while (p->oindex < p->oshift && oindex < *osamp) {
float f;
f = p->obuf[p->oindex++];
SOX_SAMPLE_CLIP_COUNT(f, effp->clips);
obuf[oindex++] = f;
}
if (p->oindex >= p->oshift && oindex<*osamp) {
p->oindex -= p->oshift;
/* shift internal output buffer */
for (i = 0; i + p->oshift < p->segment; i++)
p->obuf[i] = p->obuf[i + p->oshift];
/* pad with 0 */
for (; i < p->segment; i++)
p->obuf[i] = 0.0;
p->state = input_state;
}
}
}
*isamp = iindex;
*osamp = oindex;
return SOX_SUCCESS;
}
/*
* Drain buffer at the end
* maybe not correct ? end might be artificially faded?
*/
static int drain(sox_effect_t * effp, sox_sample_t *obuf, size_t *osamp)
{
priv_t * p = (priv_t *) effp->priv;
size_t i;
size_t oindex = 0;
if (p->state == input_state) {
for (i=p->index; i<p->segment; i++)
p->ibuf[i] = 0;
combine(p);
p->state = output_state;
}
while (oindex<*osamp && p->oindex<p->index) {
float f = p->obuf[p->oindex++];
SOX_SAMPLE_CLIP_COUNT(f, effp->clips);
obuf[oindex++] = f;
}
*osamp = oindex;
if (p->oindex == p->index)
return SOX_EOF;
else
return SOX_SUCCESS;
}
static int stop(sox_effect_t * effp)
{
priv_t * p = (priv_t *) effp->priv;
free(p->ibuf);
free(p->obuf);
free(p->fade_coefs);
return SOX_SUCCESS;
}
const sox_effect_handler_t *lsx_stretch_effect_fn(void)
{
static const sox_effect_handler_t handler = {
"stretch",
"factor [window fade shift fading]\n"
" (expansion, frame in ms, lin/..., unit<1.0, unit<0.5)\n"
" (defaults: 1.0 20 lin ...)",
SOX_EFF_LENGTH,
getopts, start, flow, drain, stop, NULL, sizeof(priv_t)
};
return &handler;
}

@ -1,520 +0,0 @@
/* libSoX direct to Sun Audio Driver
*
* Added by Chris Bagwell (cbagwell@sprynet.com) on 2/26/96
* Based on oss handler.
*
* Cleaned up changes of format somewhat in sunstartwrite on 03/31/98
*
*/
/*
* Copyright 1997 Chris Bagwell And Sundry Contributors
* This source code is freely redistributable and may be used for
* any purpose. This copyright notice must be maintained.
* Rick Richardson, Lance Norskog And Sundry Contributors are not
* responsible for the consequences of using this software.
*/
#include "sox_i.h"
#include "g711.h"
#include <sys/ioctl.h>
#include <sys/types.h>
#ifdef HAVE_SUN_AUDIOIO_H
#include <sun/audioio.h>
#else
#include <sys/audioio.h>
#endif
#include <errno.h>
#if !defined(__NetBSD__) && !defined(__OpenBSD__)
#include <stropts.h>
#endif
#include <stdlib.h>
#include <fcntl.h>
#include <string.h>
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
typedef struct
{
char* pOutput;
unsigned cOutput;
int device;
unsigned sample_shift;
} priv_t;
/*
* Do anything required before you start reading samples.
* Read file header.
* Find out sampling rate,
* size and encoding of samples,
* mono/stereo/quad.
*/
static int sunstartread(sox_format_t * ft)
{
char const* szDevname;
priv_t* pPriv = (priv_t*)ft->priv;
size_t samplesize, encoding;
audio_info_t audio_if;
#ifdef __SVR4
audio_device_t audio_dev;
#endif
char simple_hw=0;
lsx_set_signal_defaults(ft);
if (ft->filename == 0 || ft->filename[0] == 0 || !strcasecmp("default", ft->filename)) {
szDevname = "/dev/audio";
} else {
szDevname = ft->filename;
}
pPriv->device = open(szDevname, O_RDONLY);
if (pPriv->device < 0) {
lsx_fail_errno(ft, errno, "open failed for device %s", szDevname);
return SOX_EOF;
}
if (ft->encoding.encoding == SOX_ENCODING_UNKNOWN) ft->encoding.encoding = SOX_ENCODING_ULAW;
#ifdef __SVR4
/* Read in old values, change to what we need and then send back */
if (ioctl(pPriv->device, AUDIO_GETDEV, &audio_dev) < 0) {
lsx_fail_errno(ft,errno,"Unable to get information for device %s", szDevname);
return(SOX_EOF);
}
lsx_report("Hardware detected: %s",audio_dev.name);
if (strcmp("SUNW,am79c30",audio_dev.name) == 0)
{
simple_hw = 1;
}
#endif
/* If simple hardware detected in force data to ulaw. */
if (simple_hw)
{
if (ft->encoding.bits_per_sample == 8)
{
if (ft->encoding.encoding != SOX_ENCODING_ULAW &&
ft->encoding.encoding != SOX_ENCODING_ALAW)
{
lsx_report("Warning: Detected simple hardware. Forcing output to ULAW");
ft->encoding.encoding = SOX_ENCODING_ULAW;
}
}
else if (ft->encoding.bits_per_sample == 16)
{
lsx_report("Warning: Detected simple hardware. Forcing output to ULAW");
ft->encoding.bits_per_sample = 8;
ft->encoding.encoding = SOX_ENCODING_ULAW;
}
}
if (ft->encoding.bits_per_sample == 8) {
samplesize = 8;
pPriv->sample_shift = 0;
if (ft->encoding.encoding != SOX_ENCODING_ULAW &&
ft->encoding.encoding != SOX_ENCODING_ALAW &&
ft->encoding.encoding != SOX_ENCODING_SIGN2) {
lsx_fail_errno(ft,SOX_EFMT,"Sun audio driver only supports ULAW, ALAW, and signed linear for bytes.");
return (SOX_EOF);
}
if ((ft->encoding.encoding == SOX_ENCODING_ULAW ||
ft->encoding.encoding == SOX_ENCODING_ALAW) &&
ft->signal.channels == 2)
{
lsx_report("Warning: only support mono for ULAW and ALAW data. Forcing to mono.");
ft->signal.channels = 1;
}
}
else if (ft->encoding.bits_per_sample == 16) {
samplesize = 16;
pPriv->sample_shift = 1;
if (ft->encoding.encoding != SOX_ENCODING_SIGN2) {
lsx_fail_errno(ft,SOX_EFMT,"Sun audio driver only supports signed linear for words.");
return(SOX_EOF);
}
}
else {
lsx_fail_errno(ft,SOX_EFMT,"Sun audio driver only supports bytes and words");
return(SOX_EOF);
}
if (ft->signal.channels == 0)
ft->signal.channels = 1;
else if (ft->signal.channels > 1) {
lsx_report("Warning: some Sun audio devices can not play stereo");
lsx_report("at all or sometimes only with signed words. If the");
lsx_report("sound seems sluggish then this is probably the case.");
lsx_report("Try forcing output to signed words or use the avg");
lsx_report("filter to reduce the number of channels.");
ft->signal.channels = 2;
}
/* Read in old values, change to what we need and then send back */
if (ioctl(pPriv->device, AUDIO_GETINFO, &audio_if) < 0) {
lsx_fail_errno(ft,errno,"Unable to initialize %s", szDevname);
return(SOX_EOF);
}
audio_if.record.precision = samplesize;
audio_if.record.channels = ft->signal.channels;
audio_if.record.sample_rate = ft->signal.rate;
if (ft->encoding.encoding == SOX_ENCODING_ULAW)
encoding = AUDIO_ENCODING_ULAW;
else if (ft->encoding.encoding == SOX_ENCODING_ALAW)
encoding = AUDIO_ENCODING_ALAW;
else
encoding = AUDIO_ENCODING_LINEAR;
audio_if.record.encoding = encoding;
ioctl(pPriv->device, AUDIO_SETINFO, &audio_if);
if (audio_if.record.precision != samplesize) {
lsx_fail_errno(ft,errno,"Unable to initialize sample size for %s", szDevname);
return(SOX_EOF);
}
if (audio_if.record.channels != ft->signal.channels) {
lsx_fail_errno(ft,errno,"Unable to initialize number of channels for %s", szDevname);
return(SOX_EOF);
}
if (audio_if.record.sample_rate != ft->signal.rate) {
lsx_fail_errno(ft,errno,"Unable to initialize rate for %s", szDevname);
return(SOX_EOF);
}
if (audio_if.record.encoding != encoding) {
lsx_fail_errno(ft,errno,"Unable to initialize encoding for %s", szDevname);
return(SOX_EOF);
}
/* Flush any data in the buffers - its probably in the wrong format */
#if defined(__NetBSD__) || defined(__OpenBSD__)
ioctl(pPriv->device, AUDIO_FLUSH);
#elif defined __GLIBC__
ioctl(pPriv->device, (unsigned long int)I_FLUSH, FLUSHR);
#else
ioctl(pPriv->device, I_FLUSH, FLUSHR);
#endif
pPriv->cOutput = 0;
pPriv->pOutput = NULL;
return (SOX_SUCCESS);
}
static int sunstartwrite(sox_format_t * ft)
{
size_t samplesize, encoding;
audio_info_t audio_if;
#ifdef __SVR4
audio_device_t audio_dev;
#endif
char simple_hw=0;
char const* szDevname;
priv_t* pPriv = (priv_t*)ft->priv;
if (ft->filename == 0 || ft->filename[0] == 0 || !strcasecmp("default", ft->filename)) {
szDevname = "/dev/audio";
} else {
szDevname = ft->filename;
}
pPriv->device = open(szDevname, O_WRONLY);
if (pPriv->device < 0) {
lsx_fail_errno(ft, errno, "open failed for device: %s", szDevname);
return SOX_EOF;
}
#ifdef __SVR4
/* Read in old values, change to what we need and then send back */
if (ioctl(pPriv->device, AUDIO_GETDEV, &audio_dev) < 0) {
lsx_fail_errno(ft,errno,"Unable to get device information.");
return(SOX_EOF);
}
lsx_report("Hardware detected: %s",audio_dev.name);
if (strcmp("SUNW,am79c30",audio_dev.name) == 0)
{
simple_hw = 1;
}
#endif
if (simple_hw)
{
if (ft->encoding.bits_per_sample == 8)
{
if (ft->encoding.encoding != SOX_ENCODING_ULAW &&
ft->encoding.encoding != SOX_ENCODING_ALAW)
{
lsx_report("Warning: Detected simple hardware. Forcing output to ULAW");
ft->encoding.encoding = SOX_ENCODING_ULAW;
}
}
else if (ft->encoding.bits_per_sample == 16)
{
lsx_report("Warning: Detected simple hardware. Forcing output to ULAW");
ft->encoding.bits_per_sample = 8;
ft->encoding.encoding = SOX_ENCODING_ULAW;
}
}
if (ft->encoding.bits_per_sample == 8)
{
samplesize = 8;
pPriv->sample_shift = 0;
if (ft->encoding.encoding == SOX_ENCODING_UNKNOWN)
ft->encoding.encoding = SOX_ENCODING_ULAW;
else if (ft->encoding.encoding != SOX_ENCODING_ULAW &&
ft->encoding.encoding != SOX_ENCODING_ALAW &&
ft->encoding.encoding != SOX_ENCODING_SIGN2) {
lsx_report("Sun Audio driver only supports ULAW, ALAW, and Signed Linear for bytes.");
lsx_report("Forcing to ULAW");
ft->encoding.encoding = SOX_ENCODING_ULAW;
}
if ((ft->encoding.encoding == SOX_ENCODING_ULAW ||
ft->encoding.encoding == SOX_ENCODING_ALAW) &&
ft->signal.channels == 2)
{
lsx_report("Warning: only support mono for ULAW and ALAW data. Forcing to mono.");
ft->signal.channels = 1;
}
}
else if (ft->encoding.bits_per_sample == 16) {
samplesize = 16;
pPriv->sample_shift = 1;
if (ft->encoding.encoding == SOX_ENCODING_UNKNOWN)
ft->encoding.encoding = SOX_ENCODING_SIGN2;
else if (ft->encoding.encoding != SOX_ENCODING_SIGN2) {
lsx_report("Sun Audio driver only supports Signed Linear for words.");
lsx_report("Forcing to Signed Linear");
ft->encoding.encoding = SOX_ENCODING_SIGN2;
}
}
else {
lsx_report("Sun Audio driver only supports bytes and words");
ft->encoding.bits_per_sample = 16;
ft->encoding.encoding = SOX_ENCODING_SIGN2;
samplesize = 16;
pPriv->sample_shift = 1;
}
if (ft->signal.channels > 1) ft->signal.channels = 2;
/* Read in old values, change to what we need and then send back */
if (ioctl(pPriv->device, AUDIO_GETINFO, &audio_if) < 0) {
lsx_fail_errno(ft,errno,"Unable to initialize /dev/audio");
return(SOX_EOF);
}
audio_if.play.precision = samplesize;
audio_if.play.channels = ft->signal.channels;
audio_if.play.sample_rate = ft->signal.rate;
if (ft->encoding.encoding == SOX_ENCODING_ULAW)
encoding = AUDIO_ENCODING_ULAW;
else if (ft->encoding.encoding == SOX_ENCODING_ALAW)
encoding = AUDIO_ENCODING_ALAW;
else
encoding = AUDIO_ENCODING_LINEAR;
audio_if.play.encoding = encoding;
ioctl(pPriv->device, AUDIO_SETINFO, &audio_if);
if (audio_if.play.precision != samplesize) {
lsx_fail_errno(ft,errno,"Unable to initialize sample size for /dev/audio");
return(SOX_EOF);
}
if (audio_if.play.channels != ft->signal.channels) {
lsx_fail_errno(ft,errno,"Unable to initialize number of channels for /dev/audio");
return(SOX_EOF);
}
if (audio_if.play.sample_rate != ft->signal.rate) {
lsx_fail_errno(ft,errno,"Unable to initialize rate for /dev/audio");
return(SOX_EOF);
}
if (audio_if.play.encoding != encoding) {
lsx_fail_errno(ft,errno,"Unable to initialize encoding for /dev/audio");
return(SOX_EOF);
}
pPriv->cOutput = sox_globals.bufsiz >> pPriv->sample_shift;
pPriv->pOutput = lsx_malloc((size_t)pPriv->cOutput << pPriv->sample_shift);
return (SOX_SUCCESS);
}
static int sunstop(sox_format_t* ft)
{
priv_t* pPriv = (priv_t*)ft->priv;
if (pPriv->device >= 0) {
close(pPriv->device);
}
if (pPriv->pOutput) {
free(pPriv->pOutput);
}
return SOX_SUCCESS;
}
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)
static size_t sunread(sox_format_t* ft, sox_sample_t* pOutput, size_t cOutput)
{
priv_t* pPriv = (priv_t*)ft->priv;
char* pbOutput = (char*)pOutput;
size_t cbOutputLeft = cOutput << pPriv->sample_shift;
size_t i, cRead;
int cbRead;
SOX_SAMPLE_LOCALS;
LSX_USE_VAR(sox_macro_temp_double);
while (cbOutputLeft) {
cbRead = read(pPriv->device, pbOutput, cbOutputLeft);
if (cbRead <= 0) {
if (cbRead < 0) {
lsx_fail_errno(ft, errno, "Error reading from device");
return 0;
}
break;
}
cbOutputLeft -= cbRead;
pbOutput += cbRead;
}
/* Convert in-place (backwards) */
cRead = cOutput - (cbOutputLeft >> pPriv->sample_shift);
switch (pPriv->sample_shift)
{
case 0:
switch (ft->encoding.encoding)
{
case SOX_ENCODING_SIGN2:
for (i = cRead; i != 0; i--) {
pOutput[i - 1] = SOX_UNSIGNED_8BIT_TO_SAMPLE(
((sox_uint8_t*)pOutput)[i - 1],
dummy);
}
break;
case SOX_ENCODING_ULAW:
for (i = cRead; i != 0; i--) {
pOutput[i - 1] = SOX_ULAW_BYTE_TO_SAMPLE(
((sox_uint8_t*)pOutput)[i - 1],
dummy);
}
break;
case SOX_ENCODING_ALAW:
for (i = cRead; i != 0; i--) {
pOutput[i - 1] = SOX_ALAW_BYTE_TO_SAMPLE(
((sox_uint8_t*)pOutput)[i - 1],
dummy);
}
break;
default:
return 0;
}
break;
case 1:
for (i = cRead; i != 0; i--) {
pOutput[i - 1] = SOX_SIGNED_16BIT_TO_SAMPLE(
((sox_int16_t*)pOutput)[i - 1],
dummy);
}
break;
}
return cRead;
}
static size_t sunwrite(
sox_format_t* ft,
const sox_sample_t* pInput,
size_t cInput)
{
priv_t* pPriv = (priv_t*)ft->priv;
size_t cInputRemaining = cInput;
unsigned cClips = 0;
SOX_SAMPLE_LOCALS;
while (cInputRemaining) {
size_t cStride;
size_t i;
size_t cbStride;
int cbWritten;
cStride = cInputRemaining;
if (cStride > pPriv->cOutput) {
cStride = pPriv->cOutput;
}
switch (pPriv->sample_shift)
{
case 0:
switch (ft->encoding.encoding)
{
case SOX_ENCODING_SIGN2:
for (i = 0; i != cStride; i++) {
((sox_uint8_t*)pPriv->pOutput)[i] =
SOX_SAMPLE_TO_UNSIGNED_8BIT(pInput[i], cClips);
}
break;
case SOX_ENCODING_ULAW:
for (i = 0; i != cStride; i++) {
((sox_uint8_t*)pPriv->pOutput)[i] =
SOX_SAMPLE_TO_ULAW_BYTE(pInput[i], cClips);
}
break;
case SOX_ENCODING_ALAW:
for (i = 0; i != cStride; i++) {
((sox_uint8_t*)pPriv->pOutput)[i] =
SOX_SAMPLE_TO_ALAW_BYTE(pInput[i], cClips);
}
break;
default:
return 0;
}
break;
case 1:
for (i = 0; i != cStride; i++) {
((sox_int16_t*)pPriv->pOutput)[i] =
SOX_SAMPLE_TO_SIGNED_16BIT(pInput[i], cClips);
}
break;
}
cbStride = cStride << pPriv->sample_shift;
i = 0;
do {
cbWritten = write(pPriv->device, &pPriv->pOutput[i], cbStride - i);
i += cbWritten;
if (cbWritten <= 0) {
lsx_fail_errno(ft, errno, "Error writing to device");
return 0;
}
} while (i != cbStride);
cInputRemaining -= cStride;
pInput += cStride;
}
return cInput;
}
LSX_FORMAT_HANDLER(sunau)
{
static char const * const names[] = {"sunau", NULL};
static unsigned const write_encodings[] = {
SOX_ENCODING_ULAW, 8, 0,
SOX_ENCODING_ALAW, 8, 0,
SOX_ENCODING_SIGN2, 8, 16, 0,
0};
static sox_format_handler_t const handler = {SOX_LIB_VERSION_CODE,
"Sun audio device driver",
names, SOX_FILE_DEVICE | SOX_FILE_NOSTDIO,
sunstartread, sunread, sunstop,
sunstartwrite, sunwrite, sunstop,
NULL, write_encodings, NULL, sizeof(priv_t)
};
return &handler;
}

@ -1,62 +0,0 @@
/* libSoX effect: swap pairs of audio channels
*
* First version written 01/2012 by Ulrich Klauer.
* Replaces an older swap effect originally written by Chris Bagwell
* on March 16, 1999.
*
* Copyright 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
*/
#include "sox_i.h"
static int start(sox_effect_t *effp)
{
return effp->in_signal.channels >= 2 ? SOX_SUCCESS : SOX_EFF_NULL;
}
static int flow(sox_effect_t *effp, const sox_sample_t *ibuf,
sox_sample_t *obuf, size_t *isamp, size_t *osamp)
{
size_t len = min(*isamp, *osamp);
size_t channels = effp->in_signal.channels;
len /= channels;
*isamp = *osamp = len * channels;
while (len--) {
size_t i;
for (i = 0; i + 1 < channels; i += 2) {
*obuf++ = ibuf[1];
*obuf++ = ibuf[0];
ibuf += 2;
}
if (channels % 2)
*obuf++ = *ibuf++;
}
return SOX_SUCCESS;
}
sox_effect_handler_t const *lsx_swap_effect_fn(void)
{
static sox_effect_handler_t handler = {
"swap", NULL,
SOX_EFF_MCHAN | SOX_EFF_MODIFY,
NULL, start, flow, NULL, NULL, NULL,
0
};
return &handler;
}

@ -1,677 +0,0 @@
/* libSoX synth - Synthesizer Effect.
*
* Copyright (c) 2001-2009 SoX contributors
* Copyright (c) Jan 2001 Carsten Borchardt
*
* This source code is freely redistributable and may be used for any purpose.
* This copyright notice must be maintained. The authors are not responsible
* for the consequences of using this software.
*
* Except for synth types: pluck, tpdf, pinknoise, & brownnoise, and
* sweep types: linear, square & exp, which are:
*
* Copyright (c) 2006-2013 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>
#include <ctype.h>
typedef enum {
synth_sine,
synth_square,
synth_sawtooth,
synth_triangle,
synth_trapezium,
synth_trapetz = synth_trapezium, /* Deprecated name for trapezium */
synth_exp,
/* Tones above, noises below */
synth_whitenoise,
synth_noise = synth_whitenoise, /* Just a handy alias */
synth_tpdfnoise,
synth_pinknoise,
synth_brownnoise,
synth_pluck
} type_t;
static lsx_enum_item const synth_type[] = {
LSX_ENUM_ITEM(synth_, sine)
LSX_ENUM_ITEM(synth_, square)
LSX_ENUM_ITEM(synth_, sawtooth)
LSX_ENUM_ITEM(synth_, triangle)
LSX_ENUM_ITEM(synth_, trapezium)
LSX_ENUM_ITEM(synth_, trapetz)
LSX_ENUM_ITEM(synth_, exp)
LSX_ENUM_ITEM(synth_, whitenoise)
LSX_ENUM_ITEM(synth_, noise)
LSX_ENUM_ITEM(synth_, tpdfnoise)
LSX_ENUM_ITEM(synth_, pinknoise)
LSX_ENUM_ITEM(synth_, brownnoise)
LSX_ENUM_ITEM(synth_, pluck)
{0, 0}
};
typedef enum {synth_create, synth_mix, synth_amod, synth_fmod} combine_t;
static lsx_enum_item const combine_type[] = {
LSX_ENUM_ITEM(synth_, create)
LSX_ENUM_ITEM(synth_, mix)
LSX_ENUM_ITEM(synth_, amod)
LSX_ENUM_ITEM(synth_, fmod)
{0, 0}
};
typedef enum {Linear, Square, Exp, Exp_cycle} sweep_t;
typedef struct {
/* options */
type_t type;
combine_t combine;
double freq, freq2, mult;
sweep_t sweep;
double offset, phase;
double p1, p2, p3; /* Use depends on synth type */
/* internal stuff */
double lp_last_out, hp_last_out, hp_last_in, ap_last_out, ap_last_in;
double cycle_start_time_s, c0, c1, c2, c3, c4, c5, c6;
double * buffer;
size_t buffer_len, pos;
} channel_t;
/* Private data for the synthesizer */
typedef struct {
char * length_str;
channel_t * getopts_channels;
size_t getopts_nchannels;
uint64_t samples_done;
uint64_t samples_to_do;
channel_t * channels;
size_t number_of_channels;
sox_bool no_headroom;
double gain;
} priv_t;
static void create_channel(channel_t * chan)
{
memset(chan, 0, sizeof(*chan));
chan->freq2 = chan->freq = 440;
chan->p3 = chan->p2 = chan->p1 = -1;
}
static void set_default_parameters(channel_t * chan)
{
switch (chan->type) {
case synth_square: /* p1 is pulse width */
if (chan->p1 < 0)
chan->p1 = 0.5; /* default to 50% duty cycle */
break;
case synth_triangle: /* p1 is position of maximum */
if (chan->p1 < 0)
chan->p1 = 0.5;
break;
case synth_trapezium:
/* p1 is length of rising slope,
* p2 position where falling slope begins
* p3 position of end of falling slope
*/
if (chan->p1 < 0) {
chan->p1 = 0.1;
chan->p2 = 0.5;
chan->p3 = 0.6;
} else if (chan->p2 < 0) { /* try a symmetric waveform */
if (chan->p1 <= 0.5) {
chan->p2 = (1 - 2 * chan->p1) / 2;
chan->p3 = chan->p2 + chan->p1;
} else {
/* symetric is not possible, fall back to asymmetrical triangle */
chan->p2 = chan->p1;
chan->p3 = 1;
}
} else if (chan->p3 < 0)
chan->p3 = 1; /* simple falling slope to the end */
break;
case synth_exp:
if (chan->p1 < 0) /* p1 is position of maximum */
chan->p1 = 0.5;
if (chan->p2 < 0) /* p2 is amplitude */
chan->p2 = .5;
break;
case synth_pluck:
if (chan->p1 < 0)
chan->p1 = .4;
if (chan->p2 < 0)
chan->p2 = .2, chan->p3 = .9;
default: break;
}
}
#undef NUMERIC_PARAMETER
#define NUMERIC_PARAMETER(p, min, max) { \
char * end_ptr_np; \
double d_np = strtod(argv[argn], &end_ptr_np); \
if (end_ptr_np == argv[argn]) \
break; \
if (d_np < min || d_np > max || *end_ptr_np != '\0') { \
lsx_fail("parameter error"); \
return SOX_EOF; \
} \
chan->p = d_np / 100; /* adjust so abs(parameter) <= 1 */\
if (++argn == argc) \
break; \
}
static int getopts(sox_effect_t * effp, int argc, char **argv)
{
priv_t * p = (priv_t *) effp->priv;
channel_t master, * chan = &master;
int key = INT_MAX, argn = 0;
char dummy, * end_ptr;
const char *n;
--argc, ++argv;
if (argc && !strcmp(*argv, "-n")) p->no_headroom = sox_true, ++argv, --argc;
if (argc > 1 && !strcmp(*argv, "-j") && (
sscanf(argv[1], "%i %c", &key, &dummy) == 1 || (
(key = lsx_parse_note(argv[1], &end_ptr)) != INT_MAX &&
!*end_ptr))) {
argc -= 2;
argv += 2;
}
/* Get duration if given (if first arg starts with digit) */
if (argc && (isdigit((int)argv[argn][0]) || argv[argn][0] == '.')) {
p->length_str = lsx_strdup(argv[argn]);
/* Do a dummy parse of to see if it will fail */
n = lsx_parsesamples(0., p->length_str, &p->samples_to_do, 't');
if (!n || *n)
return lsx_usage(effp);
argn++;
}
create_channel(chan);
if (argn < argc) { /* [off [ph [p1 [p2 [p3]]]]]] */
do { /* break-able block */
NUMERIC_PARAMETER(offset,-100, 100)
NUMERIC_PARAMETER(phase , 0, 100)
NUMERIC_PARAMETER(p1, 0, 100)
NUMERIC_PARAMETER(p2, 0, 100)
NUMERIC_PARAMETER(p3, 0, 100)
} while (0);
}
while (argn < argc) { /* type [combine] [f1[-f2] [off [ph [p1 [p2 [p3]]]]]] */
lsx_enum_item const * enum_p = lsx_find_enum_text(argv[argn], synth_type, lsx_find_enum_item_case_sensitive);
if (enum_p == NULL) {
lsx_fail("no type given");
return SOX_EOF;
}
p->getopts_channels = lsx_realloc(p->getopts_channels, sizeof(*p->getopts_channels) * (p->getopts_nchannels + 1));
chan = &p->getopts_channels[p->getopts_nchannels++];
memcpy(chan, &master, sizeof(*chan));
chan->type = enum_p->value;
if (++argn == argc)
break;
/* maybe there is a combine-type in next arg */
enum_p = lsx_find_enum_text(argv[argn], combine_type, lsx_find_enum_item_case_sensitive);
if (enum_p != NULL) {
chan->combine = enum_p->value;
if (++argn == argc)
break;
}
/* read frequencies if given */
if (!lsx_find_enum_text(argv[argn], synth_type, lsx_find_enum_item_case_sensitive) &&
argv[argn][0] != '-') {
static const char sweeps[] = ":+/-";
chan->freq2 = chan->freq = lsx_parse_frequency_k(argv[argn], &end_ptr, key);
if (chan->freq < (chan->type == synth_pluck? 27.5 : 0) ||
(chan->type == synth_pluck && chan->freq > 4220)) {
lsx_fail("invalid freq");
return SOX_EOF;
}
if (*end_ptr && strchr(sweeps, *end_ptr)) { /* freq2 given? */
if (chan->type >= synth_noise) {
lsx_fail("can't sweep this type");
return SOX_EOF;
}
chan->sweep = strchr(sweeps, *end_ptr) - sweeps;
chan->freq2 = lsx_parse_frequency_k(end_ptr + 1, &end_ptr, key);
if (chan->freq2 < 0) {
lsx_fail("invalid freq2");
return SOX_EOF;
}
if (p->length_str == NULL) {
lsx_fail("duration must be given when using freq2");
return SOX_EOF;
}
}
if (*end_ptr) {
lsx_fail("frequency: invalid trailing character");
return SOX_EOF;
}
if (chan->sweep >= Exp && chan->freq * chan->freq2 == 0) {
lsx_fail("invalid frequency for exponential sweep");
return SOX_EOF;
}
if (++argn == argc)
break;
}
/* read rest of parameters */
do { /* break-able block */
NUMERIC_PARAMETER(offset,-100, 100)
NUMERIC_PARAMETER(phase , 0, 100)
NUMERIC_PARAMETER(p1, 0, 100)
NUMERIC_PARAMETER(p2, 0, 100)
NUMERIC_PARAMETER(p3, 0, 100)
} while (0);
}
/* If no channel parameters were given, create one default channel: */
if (!p->getopts_nchannels) {
p->getopts_channels = lsx_malloc(sizeof(*p->getopts_channels));
memcpy(&p->getopts_channels[0], &master, sizeof(channel_t));
++p->getopts_nchannels;
}
if (!effp->in_signal.channels)
effp->in_signal.channels = p->getopts_nchannels;
return SOX_SUCCESS;
}
static int start(sox_effect_t * effp)
{
priv_t * p = (priv_t *)effp->priv;
size_t i, j, k;
p->samples_done = 0;
if (p->length_str) {
if (lsx_parsesamples(effp->in_signal.rate, p->length_str, &p->samples_to_do, 't') == NULL)
return lsx_usage(effp);
} else
p->samples_to_do = effp->in_signal.length != SOX_UNKNOWN_LEN ?
effp->in_signal.length / effp->in_signal.channels : 0;
p->number_of_channels = effp->in_signal.channels;
p->channels = lsx_calloc(p->number_of_channels, sizeof(*p->channels));
for (i = 0; i < p->number_of_channels; ++i) {
channel_t * chan = &p->channels[i];
*chan = p->getopts_channels[i % p->getopts_nchannels];
set_default_parameters(chan);
if (chan->type == synth_pluck) {
double min, max, frac, p2;
/* Low pass: */
double const decay_rate = -2; /* dB / s */
double const decay_f = min(912, 266 + 106 * log(chan->freq));
double d = sqr(dB_to_linear(decay_rate / chan->freq));
d = (d * cos(2 * M_PI * decay_f / effp->in_signal.rate) - 1) / (d - 1);
chan->c0 = d - sqrt(d * d - 1);
chan->c1 = 1 - chan->c0;
/* Single-pole low pass is very rate-dependent: */
if (effp->in_signal.rate < 44100 || effp->in_signal.rate > 48000) {
lsx_fail(
"sample rate for pluck must be 44100-48000; use `rate' to resample");
return SOX_EOF;
}
/* Decay: */
chan->c1 *= exp(-2e4/ (.05+chan->p1)/ chan->freq/ effp->in_signal.rate);
/* High pass (DC-block): */
chan->c2 = exp(-2 * M_PI * 10 / effp->in_signal.rate);
chan->c3 = (1 + chan->c2) * .5;
/* All pass (for fractional delay): */
d = chan->c0 / (chan->c0 + chan->c1);
chan->buffer_len = effp->in_signal.rate / chan->freq - d;
frac = effp->in_signal.rate / chan->freq - d - chan->buffer_len;
chan->c4 = (1 - frac) / (1 + frac);
chan->pos = 0;
/* Exitation: */
chan->buffer = lsx_calloc(chan->buffer_len, sizeof(*chan->buffer));
for (k = 0, p2 = chan->p2; k < 2 && p2 >= 0; ++k, p2 = chan->p3) {
double d1 = 0, d2, colour = pow(2., 4 * (p2 - 1));
int32_t r = p2 * 100 + .5;
for (j = 0; j < chan->buffer_len; ++j) {
do d2 = d1 + (chan->phase? DRANQD1:dranqd1(r)) * colour;
while (fabs(d2) > 1);
chan->buffer[j] += d2 * (1 - .3 * k);
d1 = d2 * (colour != 1);
#ifdef TEST_PLUCK
chan->buffer[j] = sin(2 * M_PI * j / chan->buffer_len);
#endif
}
}
/* In-delay filter graduation: */
for (j = 0, min = max = 0; j < chan->buffer_len; ++j) {
double d2, t = (double)j / chan->buffer_len;
chan->lp_last_out = d2 =
chan->buffer[j] * chan->c1 + chan->lp_last_out * chan->c0;
chan->ap_last_out =
d2 * chan->c4 + chan->ap_last_in - chan->ap_last_out * chan->c4;
chan->ap_last_in = d2;
chan->buffer[j] = chan->buffer[j] * (1 - t) + chan->ap_last_out * t;
min = min(min, chan->buffer[j]);
max = max(max, chan->buffer[j]);
}
/* Normalise: */
for (j = 0, d = 0; j < chan->buffer_len; ++j) {
chan->buffer[j] = (2 * chan->buffer[j] - max - min) / (max - min);
d += sqr(chan->buffer[j]);
}
lsx_debug("rms=%f c0=%f c1=%f df=%f d3f=%f c2=%f c3=%f c4=%f frac=%f",
10 * log(d / chan->buffer_len), chan->c0, chan->c1, decay_f,
log(chan->c0)/ -2 / M_PI * effp->in_signal.rate,
chan->c2, chan->c3, chan->c4, frac);
}
switch (chan->sweep) {
case Linear: chan->mult = p->samples_to_do?
(chan->freq2 - chan->freq) / p->samples_to_do / 2 : 0;
break;
case Square: chan->mult = p->samples_to_do?
sqrt(fabs(chan->freq2 - chan->freq)) / p->samples_to_do / sqrt(3.) : 0;
if (chan->freq > chan->freq2)
chan->mult = -chan->mult;
break;
case Exp: chan->mult = p->samples_to_do?
log(chan->freq2 / chan->freq) / p->samples_to_do * effp->in_signal.rate : 1;
chan->freq /= chan->mult;
break;
case Exp_cycle: chan->mult = p->samples_to_do?
(log(chan->freq2) - log(chan->freq)) / p->samples_to_do : 1;
break;
}
lsx_debug("type=%s, combine=%s, samples_to_do=%" PRIu64 ", f1=%g, f2=%g, "
"offset=%g, phase=%g, p1=%g, p2=%g, p3=%g mult=%g",
lsx_find_enum_value(chan->type, synth_type)->text,
lsx_find_enum_value(chan->combine, combine_type)->text,
p->samples_to_do, chan->freq, chan->freq2,
chan->offset, chan->phase, chan->p1, chan->p2, chan->p3, chan->mult);
}
p->gain = 1;
effp->out_signal.mult = p->no_headroom? NULL : &p->gain;
effp->out_signal.length = p->samples_to_do ?
p->samples_to_do * effp->out_signal.channels : SOX_UNKNOWN_LEN;
return SOX_SUCCESS;
}
#define elapsed_time_s p->samples_done / effp->in_signal.rate
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;
unsigned len = min(*isamp, *osamp) / effp->in_signal.channels;
unsigned c, done;
int result = SOX_SUCCESS;
for (done = 0; done < len && result == SOX_SUCCESS; ++done) {
for (c = 0; c < effp->in_signal.channels; c++) {
sox_sample_t synth_input = *ibuf++;
channel_t * chan = &p->channels[c];
double synth_out; /* [-1, 1] */
if (chan->type < synth_noise) { /* Need to calculate phase: */
double phase; /* [0, 1) */
switch (chan->sweep) {
case Linear:
phase = (chan->freq + p->samples_done * chan->mult) *
elapsed_time_s;
break;
case Square:
phase = (chan->freq + sign(chan->mult) *
sqr(p->samples_done * chan->mult)) * elapsed_time_s;
break;
case Exp:
phase = chan->freq * exp(chan->mult * elapsed_time_s);
break;
case Exp_cycle: default: {
double f = chan->freq * exp(p->samples_done * chan->mult);
double cycle_elapsed_time_s = elapsed_time_s - chan->cycle_start_time_s;
if (f * cycle_elapsed_time_s >= 1) { /* move to next cycle */
chan->cycle_start_time_s += 1 / f;
cycle_elapsed_time_s = elapsed_time_s - chan->cycle_start_time_s;
}
phase = f * cycle_elapsed_time_s;
break;
}
}
phase = fmod(phase + chan->phase, 1.0);
switch (chan->type) {
case synth_sine:
synth_out = sin(2 * M_PI * phase);
break;
case synth_square:
/* |_______ | +1
* | | |
* |_______|__________| 0
* | | |
* | |__________| -1
* | |
* 0 p1 1
*/
synth_out = -1 + 2 * (phase < chan->p1);
break;
case synth_sawtooth:
/* | __| +1
* | __/ |
* |_______/_____| 0
* | __/ |
* |_/ | -1
* | |
* 0 1
*/
synth_out = -1 + 2 * phase;
break;
case synth_triangle:
/* | . | +1
* | / \ |
* |__/___\__| 0
* | / \ |
* |/ \| -1
* | |
* 0 p1 1
*/
if (phase < chan->p1)
synth_out = -1 + 2 * phase / chan->p1; /* In rising part of period */
else
synth_out = 1 - 2 * (phase - chan->p1) / (1 - chan->p1); /* In falling part */
break;
case synth_trapezium:
/* | ______ |+1
* | / \ |
* |__/________\___________| 0
* | / \ |
* |/ \_________|-1
* | |
* 0 p1 p2 p3 1
*/
if (phase < chan->p1) /* In rising part of period */
synth_out = -1 + 2 * phase / chan->p1;
else if (phase < chan->p2) /* In high part of period */
synth_out = 1;
else if (phase < chan->p3) /* In falling part */
synth_out = 1 - 2 * (phase - chan->p2) / (chan->p3 - chan->p2);
else /* In low part of period */
synth_out = -1;
break;
case synth_exp:
/* | | | +1
* | | | |
* | _| |_ | 0
* | __- -__ |
* |____--- ---____ | f(p2)
* | |
* 0 p1 1
*/
synth_out = dB_to_linear(chan->p2 * -200); /* 0 .. 1 */
if (phase < chan->p1)
synth_out = synth_out * exp(phase * log(1 / synth_out) / chan->p1);
else
synth_out = synth_out * exp((1 - phase) * log(1 / synth_out) / (1 - chan->p1));
synth_out = synth_out * 2 - 1; /* map 0 .. 1 to -1 .. +1 */
break;
default: synth_out = 0;
}
} else switch (chan->type) {
case synth_whitenoise:
synth_out = DRANQD1;
break;
case synth_tpdfnoise:
synth_out = .5 * (DRANQD1 + DRANQD1);
break;
case synth_pinknoise: { /* "Paul Kellet's refined method" */
#define _ .125 / (65536. * 32768.)
double d = RANQD1;
chan->c0 = .99886 * chan->c0 + d * (.0555179*_);
chan->c1 = .99332 * chan->c1 + d * (.0750759*_);
chan->c2 = .96900 * chan->c2 + d * (.1538520*_);
chan->c3 = .86650 * chan->c3 + d * (.3104856*_);
chan->c4 = .55000 * chan->c4 + d * (.5329522*_);
chan->c5 = -.7616 * chan->c5 - d * (.0168980*_);
synth_out = chan->c0 + chan->c1 + chan->c2 + chan->c3
+ chan->c4 + chan->c5 + chan->c6 + d * (.5362*_);
chan->c6 = d * (.115926*_);
break;
#undef _
}
case synth_brownnoise:
do synth_out = chan->lp_last_out + DRANQD1 * (1. / 16);
while (fabs(synth_out) > 1);
chan->lp_last_out = synth_out;
break;
case synth_pluck: {
double d = chan->buffer[chan->pos];
chan->hp_last_out =
(d - chan->hp_last_in) * chan->c3 + chan->hp_last_out * chan->c2;
chan->hp_last_in = d;
synth_out = range_limit(chan->hp_last_out, -1, 1);
chan->lp_last_out = d = d * chan->c1 + chan->lp_last_out * chan->c0;
chan->ap_last_out = chan->buffer[chan->pos] =
(d - chan->ap_last_out) * chan->c4 + chan->ap_last_in;
chan->ap_last_in = d;
chan->pos = chan->pos + 1 == chan->buffer_len? 0 : chan->pos + 1;
break;
}
default: synth_out = 0;
}
/* Add offset, but prevent clipping: */
synth_out = synth_out * (1 - fabs(chan->offset)) + chan->offset;
switch (chan->combine) {
case synth_create: synth_out *= SOX_SAMPLE_MAX; break;
case synth_mix : synth_out = (synth_out * SOX_SAMPLE_MAX + synth_input) * .5; break;
case synth_amod : synth_out = (synth_out + 1) * synth_input * .5; break;
case synth_fmod : synth_out *= synth_input; break;
}
*obuf++ = synth_out < 0? synth_out * p->gain - .5 : synth_out * p->gain + .5;
}
if (++p->samples_done == p->samples_to_do)
result = SOX_EOF;
}
*isamp = *osamp = done * effp->in_signal.channels;
return result;
}
static int stop(sox_effect_t * effp)
{
priv_t * p = (priv_t *) effp->priv;
size_t i;
for (i = 0; i < p->number_of_channels; ++i)
free(p->channels[i].buffer);
free(p->channels);
return SOX_SUCCESS;
}
static int lsx_kill(sox_effect_t * effp)
{
priv_t * p = (priv_t *) effp->priv;
free(p->getopts_channels);
free(p->length_str);
return SOX_SUCCESS;
}
const sox_effect_handler_t *lsx_synth_effect_fn(void)
{
static sox_effect_handler_t handler = {
"synth", "[-j KEY] [-n] [length [offset [phase [p1 [p2 [p3]]]]]]] {type [combine] [[%]freq[k][:|+|/|-[%]freq2[k]] [offset [phase [p1 [p2 [p3]]]]]]}",
SOX_EFF_MCHAN | SOX_EFF_LENGTH | SOX_EFF_GAIN,
getopts, start, flow, 0, stop, lsx_kill, sizeof(priv_t)
};
return &handler;
}

@ -1,47 +0,0 @@
/* libSoX effect: tremolo (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
*/
#include "sox_i.h"
static int getopts(sox_effect_t * effp, int argc, char * * argv)
{
double speed, depth = 40;
char dummy; /* To check for extraneous chars. */
char offset[100];
char * args[] = {0, "sine", "fmod", 0, 0, "25"};
if (argc < 2 || argc > 3 ||
sscanf(argv[1], "%lf %c", &speed, &dummy) != 1 || speed < 0 ||
(argc > 2 && sscanf(argv[2], "%lf %c", &depth, &dummy) != 1) ||
depth <= 0 || depth > 100)
return lsx_usage(effp);
args[0] = argv[0];
args[3] = argv[1];
sprintf(offset, "%g", 100 - depth / 2);
args[4] = offset;
return lsx_synth_effect_fn()->getopts(effp, (int)array_length(args), args);
}
sox_effect_handler_t const * lsx_tremolo_effect_fn(void)
{
static sox_effect_handler_t handler;
handler = *lsx_synth_effect_fn();
handler.name = "tremolo";
handler.usage = "speed_Hz [depth_percent]";
handler.getopts = getopts;
return &handler;
}

@ -1,216 +0,0 @@
/* libSoX effect: trim - cut portions out of the audio
*
* First version written 01/2012 by Ulrich Klauer.
* Replaces an older trim effect originally written by Curt Zirzow in 2000.
*
* Copyright 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
*/
#include "sox_i.h"
typedef struct {
/* parameters */
unsigned int num_pos;
struct {
uint64_t sample; /* NB: wide samples */
char *argstr;
} *pos;
/* state */
unsigned int current_pos;
uint64_t samples_read; /* NB: wide samples */
sox_bool copying;
} priv_t;
static int parse(sox_effect_t *effp, int argc, char **argv)
{
priv_t *p = (priv_t*) effp->priv;
unsigned int i;
--argc, ++argv;
p->num_pos = argc;
lsx_Calloc(p->pos, p->num_pos);
for (i = 0; i < p->num_pos; i++) {
const char *arg = argv[i];
p->pos[i].argstr = lsx_strdup(arg);
/* dummy parse to check for syntax errors */
arg = lsx_parseposition(0., arg, NULL, (uint64_t)0, (uint64_t)0, '+');
if (!arg || *arg) {
lsx_fail("Error parsing position %u", i+1);
return lsx_usage(effp);
}
}
return SOX_SUCCESS;
}
static int start(sox_effect_t *effp)
{
priv_t *p = (priv_t*) effp->priv;
uint64_t in_length = effp->in_signal.length != SOX_UNKNOWN_LEN ?
effp->in_signal.length / effp->in_signal.channels : SOX_UNKNOWN_LEN;
uint64_t last_seen = 0;
sox_bool open_end;
unsigned int i;
p->copying = sox_false;
/* calculate absolute positions */
for (i = 0; i < p->num_pos; i++) {
if (!lsx_parseposition(effp->in_signal.rate, p->pos[i].argstr, &p->pos[i].sample, last_seen, in_length, '+')) {
lsx_fail("Position %u is relative to end of audio, but audio length is unknown", i+1);
return SOX_EOF;
}
last_seen = p->pos[i].sample;
lsx_debug_more("position %u at %" PRIu64, i+1, last_seen);
}
/* sanity checks */
last_seen = 0;
for (i = 0; i < p->num_pos; i++) {
if (p->pos[i].sample < last_seen) {
lsx_fail("Position %u is behind the following position.", i);
return SOX_EOF;
}
last_seen = p->pos[i].sample;
}
if (p->num_pos && in_length != SOX_UNKNOWN_LEN)
if (p->pos[0].sample > in_length ||
p->pos[p->num_pos-1].sample > in_length)
lsx_warn("%s position is after expected end of audio.",
p->pos[0].sample > in_length ? "Start" : "End");
/* avoid unnecessary work */
if (in_length == SOX_UNKNOWN_LEN)
while (p->num_pos && p->pos[p->num_pos-1].sample == SOX_UNKNOWN_LEN) {
lsx_debug_more("removing `-0' position");
p->num_pos--;
free(p->pos[p->num_pos].argstr);
}
if (p->num_pos == 1 && !p->pos[0].sample)
return SOX_EFF_NULL;
/* calculate output length */
open_end = p->num_pos % 2;
if (open_end && in_length == SOX_UNKNOWN_LEN)
effp->out_signal.length = SOX_UNKNOWN_LEN;
else {
effp->out_signal.length = 0;
for (i = 0; i+1 < p->num_pos ; i += 2)
effp->out_signal.length +=
min(p->pos[i+1].sample, in_length) - min(p->pos[i].sample, in_length);
if (open_end)
effp->out_signal.length +=
in_length - min(p->pos[p->num_pos-1].sample, in_length);
effp->out_signal.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 len = min(*isamp, *osamp);
size_t channels = effp->in_signal.channels;
len /= channels;
*isamp = *osamp = 0;
while (len) {
size_t chunk;
if (p->current_pos < p->num_pos &&
p->samples_read == p->pos[p->current_pos].sample) {
p->copying = !p->copying;
p->current_pos++;
}
if (p->current_pos >= p->num_pos && !p->copying)
return SOX_EOF;
chunk = p->current_pos < p->num_pos ?
min(len, p->pos[p->current_pos].sample - p->samples_read) : len;
if (p->copying) {
memcpy(obuf, ibuf, chunk * channels * sizeof(*obuf));
obuf += chunk * channels, *osamp += chunk * channels;
}
ibuf += chunk * channels; *isamp += chunk * channels;
p->samples_read += chunk, len -= chunk;
}
return SOX_SUCCESS;
}
static int drain(sox_effect_t *effp, sox_sample_t *obuf UNUSED, size_t *osamp)
{
priv_t *p = (priv_t*) effp->priv;
*osamp = 0; /* only checking for errors */
if (p->current_pos + 1 == p->num_pos &&
p->pos[p->current_pos].sample == p->samples_read &&
p->copying) /* would stop here anyway */
p->current_pos++;
if (p->current_pos < p->num_pos)
lsx_warn("Last %u position(s) not reached%s.",
p->num_pos - p->current_pos,
(effp->in_signal.length == SOX_UNKNOWN_LEN ||
effp->in_signal.length/effp->in_signal.channels == p->samples_read) ?
"" /* unknown length, or did already warn during start() */ :
" (audio shorter than expected)"
);
return SOX_EOF;
}
static int lsx_kill(sox_effect_t *effp)
{
unsigned int i;
priv_t *p = (priv_t*) effp->priv;
for (i = 0; i < p->num_pos; i++)
free(p->pos[i].argstr);
free(p->pos);
return SOX_SUCCESS;
}
sox_effect_handler_t const *lsx_trim_effect_fn(void)
{
static sox_effect_handler_t handler = {
"trim", "{position}",
SOX_EFF_MCHAN | SOX_EFF_LENGTH | SOX_EFF_MODIFY,
parse, start, flow, drain, NULL, lsx_kill,
sizeof(priv_t)
};
return &handler;
}
/* The following functions allow a libSoX client to do a speed
* optimization, by asking for the number of samples to be skipped
* at the beginning of the audio with sox_trim_get_start(), skipping
* that many samples in an efficient way such as seeking within the
* input file, then telling us it has been done by calling
* sox_trim_clear_start() (the name is historical).
* Note that sox_trim_get_start() returns the number of non-wide
* samples. */
sox_uint64_t sox_trim_get_start(sox_effect_t *effp)
{
priv_t *p = (priv_t*) effp->priv;
return p->num_pos ? p->pos[0].sample * effp->in_signal.channels : 0;
}
void sox_trim_clear_start(sox_effect_t *effp)
{
priv_t *p = (priv_t*) effp->priv;
p->samples_read = p->num_pos ? p->pos[0].sample : 0;
}

Some files were not shown because too many files have changed in this diff Show More

Loading…
Cancel
Save