parent
							
								
									1ad8783ff7
								
							
						
					
					
						commit
						c21a2cf584
					
				| @ -1,72 +0,0 @@ | ||||
| 
 | ||||
| set(PROJECT_NAME sox) | ||||
| 
 | ||||
| include_directories(${CMAKE_CURRENT_BINARY_DIR}) | ||||
| 
 | ||||
| if(CMAKE_COMPILER_IS_GNUCC) | ||||
|     execute_process(COMMAND ${CMAKE_C_COMPILER} -dumpversion | ||||
|             OUTPUT_VARIABLE ver) | ||||
|     string(REGEX REPLACE "([0-9]+)\\.([0-9]+).*" "\\1" major "${ver}") | ||||
|     string(REGEX REPLACE "([0-9]+)\\.([0-9]+).*" "\\2" minor "${ver}") | ||||
|     math(EXPR ver "100 * ${major} + ${minor}") | ||||
|     if(${ver} LESS 403) | ||||
|         add_definitions(-Wconversion) | ||||
|     else(${ver} LESS 403) | ||||
|         add_definitions(-Wtraditional-conversion) | ||||
|     endif(${ver} LESS 403) | ||||
| endif(CMAKE_COMPILER_IS_GNUCC) | ||||
| 
 | ||||
| if (NOT EXTERNAL_GSM) | ||||
|     set(optional_libs ${optional_libs} gsm) | ||||
| endif (NOT EXTERNAL_GSM) | ||||
| 
 | ||||
| set(effects_srcs | ||||
|         delay.c | ||||
|         downsample.c | ||||
|         echo.c | ||||
|         echos.c | ||||
|         fft4g.c | ||||
|         input.c | ||||
|         output.c | ||||
|         reverb.c | ||||
|         speed.c | ||||
|         tempo.c | ||||
|         upsample.c | ||||
|         vad.c | ||||
|         vol.c | ||||
|         ) | ||||
| set(formats_srcs | ||||
|         adpcm.c | ||||
|         g711.c | ||||
|         ima_rw.c | ||||
|         raw.c | ||||
|         wav.c | ||||
|         ) | ||||
| 
 | ||||
| include_directories(${CMAKE_CURRENT_SOURCE_DIR}/bit-rot) | ||||
| 
 | ||||
| add_library(${PROJECT_NAME} STATIC | ||||
|         ${effects_srcs} | ||||
|         effects.c | ||||
|         effects_i.c | ||||
|         effects_i_dsp.c | ||||
|         ${formats_srcs} | ||||
|         formats_i.c | ||||
|         formats.c | ||||
|         getopt.c | ||||
|         libsox_i.c | ||||
|         libsox.c | ||||
|         util.c | ||||
|         xmalloc.c | ||||
|         ) | ||||
| 
 | ||||
| target_include_directories(${PROJECT_NAME} PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}) | ||||
| 
 | ||||
| find_program(LN ln) | ||||
| if (LN) | ||||
|     add_custom_target(rec ALL ${LN} -sf sox rec DEPENDS sox) | ||||
|     add_custom_target(play ALL ${LN} -sf sox play DEPENDS sox) | ||||
|     add_custom_target(soxi ALL ${LN} -sf sox soxi DEPENDS sox) | ||||
| endif (LN) | ||||
| find_program(CTAGS NAMES exuberant-ctags ctags) | ||||
| add_custom_target(tags ${CTAGS} --recurse --extra=fq .) | ||||
| @ -1,367 +0,0 @@ | ||||
| /* adpcm.c  codex functions for MS_ADPCM data
 | ||||
|  *          (hopefully) provides interoperability with | ||||
|  *          Microsoft's ADPCM format, but, as usual, | ||||
|  *          see LACK-OF-WARRANTY information below. | ||||
|  * | ||||
|  *      Copyright (C) 1999 Stanley J. Brooks <stabro@megsinet.net> | ||||
|  * | ||||
|  * This library is free software; you can redistribute it and/or modify it | ||||
|  * under the terms of the GNU Lesser General Public License as published by | ||||
|  * the Free Software Foundation; either version 2.1 of the License, or (at | ||||
|  * your option) any later version. | ||||
|  * | ||||
|  * This library is distributed in the hope that it will be useful, but | ||||
|  * WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser | ||||
|  * General Public License for more details. | ||||
|  * | ||||
|  * You should have received a copy of the GNU Lesser General Public License | ||||
|  * along with this library; if not, write to the Free Software Foundation, | ||||
|  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA | ||||
|  * | ||||
|  */ | ||||
| 
 | ||||
| /*
 | ||||
|  * November 22, 1999 | ||||
|  *  specs I've seen are unclear about ADPCM supporting more than 2 channels, | ||||
|  *  but these routines support more channels in a manner which looks (IMHO) | ||||
|  *  like the most natural extension. | ||||
|  * | ||||
|  *  Remark: code still turbulent, encoding very new. | ||||
|  * | ||||
|  */ | ||||
| 
 | ||||
| #include "sox_i.h" | ||||
| #include "adpcm.h" | ||||
| 
 | ||||
| #include <sys/types.h> | ||||
| #include <stdio.h> | ||||
| 
 | ||||
| typedef struct { | ||||
|         sox_sample_t  step;      /* step size */ | ||||
|         short coef[2]; | ||||
| } MsState_t; | ||||
| 
 | ||||
| #define lsbshortldi(x,p) { (x)=((short)((int)(p)[0] + ((int)(p)[1]<<8))); (p) += 2; } | ||||
| 
 | ||||
| /*
 | ||||
|  * Lookup tables for MS ADPCM format | ||||
|  */ | ||||
| 
 | ||||
| /* these are step-size adjust factors, where
 | ||||
|  * 1.0 is scaled to 0x100 | ||||
|  */ | ||||
| static const | ||||
| sox_sample_t stepAdjustTable[] = { | ||||
|         230, 230, 230, 230, 307, 409, 512, 614, | ||||
|         768, 614, 512, 409, 307, 230, 230, 230 | ||||
| }; | ||||
| 
 | ||||
| /* TODO : The first 7 lsx_ms_adpcm_i_coef sets are always hardcoded and must
 | ||||
|    appear in the actual WAVE file.  They should be read in | ||||
|    in case a sound program added extras to the list. */ | ||||
| 
 | ||||
| const short lsx_ms_adpcm_i_coef[7][2] = { | ||||
|                         { 256,   0}, | ||||
|                         { 512,-256}, | ||||
|                         {   0,   0}, | ||||
|                         { 192,  64}, | ||||
|                         { 240,   0}, | ||||
|                         { 460,-208}, | ||||
|                         { 392,-232} | ||||
| }; | ||||
| 
 | ||||
| extern void *lsx_ms_adpcm_alloc(unsigned chans) | ||||
| { | ||||
|         return lsx_malloc(chans * sizeof(MsState_t)); | ||||
| } | ||||
| 
 | ||||
| static inline sox_sample_t AdpcmDecode(sox_sample_t c, MsState_t *state, | ||||
|                                sox_sample_t sample1, sox_sample_t sample2) | ||||
| { | ||||
|         sox_sample_t vlin; | ||||
|         sox_sample_t sample; | ||||
|         sox_sample_t step; | ||||
| 
 | ||||
|         /** Compute next step value **/ | ||||
|         step = state->step; | ||||
|         { | ||||
|                 sox_sample_t nstep; | ||||
|                 nstep = (stepAdjustTable[c] * step) >> 8; | ||||
|                 state->step = (nstep < 16)? 16:nstep; | ||||
|         } | ||||
| 
 | ||||
|         /** make linear prediction for next sample **/ | ||||
|         vlin = | ||||
|                         ((sample1 * state->coef[0]) + | ||||
|                          (sample2 * state->coef[1])) >> 8; | ||||
|         /** then add the code*step adjustment **/ | ||||
|         c -= (c & 0x08) << 1; | ||||
|         sample = (c * step) + vlin; | ||||
| 
 | ||||
|         if (sample > 0x7fff) sample = 0x7fff; | ||||
|         else if (sample < -0x8000) sample = -0x8000; | ||||
| 
 | ||||
|         return (sample); | ||||
| } | ||||
| 
 | ||||
| /* lsx_ms_adpcm_block_expand_i() outputs interleaved samples into one output buffer */ | ||||
| const char *lsx_ms_adpcm_block_expand_i( | ||||
|         void *priv, | ||||
|         unsigned chans,          /* total channels             */ | ||||
|         int nCoef, | ||||
|         const short *coef, | ||||
|         const unsigned char *ibuff,/* input buffer[blockAlign]   */ | ||||
|         SAMPL *obuff,       /* output samples, n*chans    */ | ||||
|         int n               /* samples to decode PER channel */ | ||||
| ) | ||||
| { | ||||
|   const unsigned char *ip; | ||||
|   unsigned ch; | ||||
|   const char *errmsg = NULL; | ||||
|   MsState_t *state = priv;  /* One decompressor state for each channel */ | ||||
| 
 | ||||
|   /* Read the four-byte header for each channel */ | ||||
|   ip = ibuff; | ||||
|   for (ch = 0; ch < chans; ch++) { | ||||
|     unsigned char bpred = *ip++; | ||||
|     if (bpred >= nCoef) { | ||||
|       errmsg = "MSADPCM bpred >= nCoef, arbitrarily using 0\n"; | ||||
|       bpred = 0; | ||||
|     } | ||||
|     state[ch].coef[0] = coef[(int)bpred*2+0]; | ||||
|     state[ch].coef[1] = coef[(int)bpred*2+1]; | ||||
|   } | ||||
| 
 | ||||
|   for (ch = 0; ch < chans; ch++) | ||||
|     lsbshortldi(state[ch].step, ip); | ||||
| 
 | ||||
|   /* sample1's directly into obuff */ | ||||
|   for (ch = 0; ch < chans; ch++) | ||||
|     lsbshortldi(obuff[chans+ch], ip); | ||||
| 
 | ||||
|   /* sample2's directly into obuff */ | ||||
|   for (ch = 0; ch < chans; ch++) | ||||
|     lsbshortldi(obuff[ch], ip); | ||||
| 
 | ||||
|   { | ||||
|     unsigned ch2; | ||||
|     unsigned char b; | ||||
|     short *op, *top, *tmp; | ||||
| 
 | ||||
|     /* already have 1st 2 samples from block-header */ | ||||
|     op = obuff + 2*chans; | ||||
|     top = obuff + n*chans; | ||||
| 
 | ||||
|     ch2 = 0; | ||||
|     while (op < top) { /*** N.B. Without int casts, crashes on 64-bit arch ***/ | ||||
|       b = *ip++; | ||||
|       tmp = op; | ||||
|       *op++ = AdpcmDecode(b >> 4, state+ch2, tmp[-(int)chans], tmp[-(int)(2*chans)]); | ||||
|       if (++ch2 == chans) ch2 = 0; | ||||
|       tmp = op; | ||||
|       *op++ = AdpcmDecode(b&0x0f, state+ch2, tmp[-(int)chans], tmp[-(int)(2*chans)]); | ||||
|       if (++ch2 == chans) ch2 = 0; | ||||
|     } | ||||
|   } | ||||
|   return errmsg; | ||||
| } | ||||
| 
 | ||||
| static int AdpcmMashS( | ||||
|         unsigned ch,              /* channel number to encode, REQUIRE 0 <= ch < chans  */ | ||||
|         unsigned chans,           /* total channels */ | ||||
|         SAMPL v[2],          /* values to use as starting 2 */ | ||||
|         const short coef[2],/* lin predictor coeffs */ | ||||
|         const SAMPL *ibuff,  /* ibuff[] is interleaved input samples */ | ||||
|         int n,               /* samples to encode PER channel */ | ||||
|         int *iostep,         /* input/output step, REQUIRE 16 <= *st <= 0x7fff */ | ||||
|         unsigned char *obuff /* output buffer[blockAlign], or NULL for no output  */ | ||||
| ) | ||||
| { | ||||
|         const SAMPL *ip, *itop; | ||||
|         unsigned char *op; | ||||
|         int ox = 0;      /*  */ | ||||
|         int d, v0, v1, step; | ||||
|         double d2;       /* long long is okay also, speed abt the same */ | ||||
| 
 | ||||
|         ip = ibuff + ch;       /* point ip to 1st input sample for this channel */ | ||||
|         itop = ibuff + n*chans; | ||||
|         v0 = v[0]; | ||||
|         v1 = v[1]; | ||||
|         d = *ip - v1; ip += chans; /* 1st input sample for this channel */ | ||||
|         d2 = d*d;  /* d2 will be sum of squares of errors, given input v0 and *st */ | ||||
|         d = *ip - v0; ip += chans; /* 2nd input sample for this channel */ | ||||
|         d2 += d*d; | ||||
| 
 | ||||
|         step = *iostep; | ||||
| 
 | ||||
|         op = obuff;            /* output pointer (or NULL) */ | ||||
|         if (op) {              /* NULL means don't output, just compute the rms error */ | ||||
|                 op += chans;         /* skip bpred indices */ | ||||
|                 op += 2*ch;          /* channel's stepsize */ | ||||
|                 op[0] = step; op[1] = step>>8; | ||||
|                 op += 2*chans;       /* skip to v0 */ | ||||
|                 op[0] = v0; op[1] = v0>>8; | ||||
|                 op += 2*chans;       /* skip to v1 */ | ||||
|                 op[0] = v1; op[1] = v1>>8; | ||||
|                 op = obuff+7*chans;  /* point to base of output nibbles */ | ||||
|                 ox = 4*ch; | ||||
|         } | ||||
|         for (; ip < itop; ip+=chans) { | ||||
|                 int vlin,d3,dp,c; | ||||
| 
 | ||||
|           /* make linear prediction for next sample */ | ||||
|                 vlin = (v0 * coef[0] + v1 * coef[1]) >> 8; | ||||
|                 d3 = *ip - vlin;  /* difference between linear prediction and current sample */ | ||||
|                 dp = d3 + (step<<3) + (step>>1); | ||||
|                 c = 0; | ||||
|                 if (dp>0) { | ||||
|                         c = dp/step; | ||||
|                         if (c>15) c = 15; | ||||
|                 } | ||||
|                 c -= 8; | ||||
|                 dp = c * step;   /* quantized estimate of samp - vlin */ | ||||
|                 c &= 0x0f;       /* mask to 4 bits */ | ||||
| 
 | ||||
|                 v1 = v0; /* shift history */ | ||||
|                 v0 = vlin + dp; | ||||
|                 if (v0<-0x8000) v0 = -0x8000; | ||||
|                 else if (v0>0x7fff) v0 = 0x7fff; | ||||
| 
 | ||||
|                 d3 = *ip - v0; | ||||
|                 d2 += d3*d3; /* update square-error */ | ||||
| 
 | ||||
|                 if (op) {   /* if we want output, put it in proper place */ | ||||
|                         op[ox>>3] |= (ox&4)? c:(c<<4); | ||||
|                         ox += 4*chans; | ||||
|                         lsx_debug_more("%.1x",c); | ||||
| 
 | ||||
|                 } | ||||
| 
 | ||||
|                 /* Update the step for the next sample */ | ||||
|                 step = (stepAdjustTable[c] * step) >> 8; | ||||
|                 if (step < 16) step = 16; | ||||
| 
 | ||||
|         } | ||||
|         if (op) lsx_debug_more("\n"); | ||||
|         d2 /= n; /* be sure it's non-negative */ | ||||
|         lsx_debug_more("ch%d: st %d->%d, d %.1f\n", ch, *iostep, step, sqrt(d2)); | ||||
|         *iostep = step; | ||||
|         return (int) sqrt(d2); | ||||
| } | ||||
| 
 | ||||
| static inline void AdpcmMashChannel( | ||||
|         unsigned ch,             /* channel number to encode, REQUIRE 0 <= ch < chans  */ | ||||
|         unsigned chans,          /* total channels */ | ||||
|         const SAMPL *ip,    /* ip[] is interleaved input samples */ | ||||
|         int n,              /* samples to encode PER channel, REQUIRE */ | ||||
|         int *st,            /* input/output steps, 16<=st[i] */ | ||||
|         unsigned char *obuff /* output buffer[blockAlign] */ | ||||
| ) | ||||
| { | ||||
|         SAMPL v[2]; | ||||
|         int n0,s0,s1,ss,smin; | ||||
|         int dmin,k,kmin; | ||||
| 
 | ||||
|         n0 = n/2; if (n0>32) n0=32; | ||||
|         if (*st<16) *st = 16; | ||||
|         v[1] = ip[ch]; | ||||
|         v[0] = ip[ch+chans]; | ||||
| 
 | ||||
|         dmin = 0; kmin = 0; smin = 0; | ||||
|         /* for each of 7 standard coeff sets, we try compression
 | ||||
|          * beginning with last step-value, and with slightly | ||||
|          * forward-adjusted step-value, taking best of the 14 | ||||
|          */ | ||||
|         for (k=0; k<7; k++) { | ||||
|                 int d0,d1; | ||||
|                 ss = s0 = *st; | ||||
|                 d0=AdpcmMashS(ch, chans, v, lsx_ms_adpcm_i_coef[k], ip, n, &ss, NULL); /* with step s0 */ | ||||
| 
 | ||||
|                 s1 = s0; | ||||
|                 AdpcmMashS(ch, chans, v, lsx_ms_adpcm_i_coef[k], ip, n0, &s1, NULL); | ||||
|                 lsx_debug_more(" s32 %d\n",s1); | ||||
|                 ss = s1 = (3*s0+s1)/4; | ||||
|                 d1=AdpcmMashS(ch, chans, v, lsx_ms_adpcm_i_coef[k], ip, n, &ss, NULL); /* with step s1 */ | ||||
|                 if (!k || d0<dmin || d1<dmin) { | ||||
|                         kmin = k; | ||||
|                         if (d0<=d1) { | ||||
|                                 dmin = d0; | ||||
|                                 smin = s0; | ||||
|                         }else{ | ||||
|                                 dmin = d1; | ||||
|                                 smin = s1; | ||||
|                         } | ||||
|                 } | ||||
|         } | ||||
|         *st = smin; | ||||
|         lsx_debug_more("kmin %d, smin %5d, ",kmin,smin); | ||||
|         AdpcmMashS(ch, chans, v, lsx_ms_adpcm_i_coef[kmin], ip, n, st, obuff); | ||||
|         obuff[ch] = kmin; | ||||
| } | ||||
| 
 | ||||
| void lsx_ms_adpcm_block_mash_i( | ||||
|         unsigned chans,          /* total channels */ | ||||
|         const SAMPL *ip,    /* ip[n*chans] is interleaved input samples */ | ||||
|         int n,              /* samples to encode PER channel */ | ||||
|         int *st,            /* input/output steps, 16<=st[i] */ | ||||
|         unsigned char *obuff,      /* output buffer[blockAlign]     */ | ||||
|         int blockAlign      /* >= 7*chans + chans*(n-2)/2.0    */ | ||||
| ) | ||||
| { | ||||
|         unsigned ch; | ||||
|         unsigned char *p; | ||||
| 
 | ||||
|         lsx_debug_more("AdpcmMashI(chans %d, ip %p, n %d, st %p, obuff %p, bA %d)\n", | ||||
|             chans, (void *)ip, n, (void *)st, obuff, blockAlign); | ||||
| 
 | ||||
|         for (p=obuff+7*chans; p<obuff+blockAlign; p++) *p=0; | ||||
| 
 | ||||
|         for (ch=0; ch<chans; ch++) | ||||
|                 AdpcmMashChannel(ch, chans, ip, n, st+ch, obuff); | ||||
| } | ||||
| 
 | ||||
| /*
 | ||||
|  * lsx_ms_adpcm_samples_in(dataLen, chans, blockAlign, samplesPerBlock) | ||||
|  *  returns the number of samples/channel which would be | ||||
|  *  in the dataLen, given the other parameters ... | ||||
|  *  if input samplesPerBlock is 0, then returns the max | ||||
|  *  samplesPerBlock which would go into a block of size blockAlign | ||||
|  *  Yes, it is confusing usage. | ||||
|  */ | ||||
| size_t lsx_ms_adpcm_samples_in( | ||||
|         size_t dataLen, | ||||
|         size_t chans, | ||||
|         size_t blockAlign, | ||||
|         size_t samplesPerBlock | ||||
| ){ | ||||
|         size_t m, n; | ||||
| 
 | ||||
|         if (samplesPerBlock) { | ||||
|                 n = (dataLen / blockAlign) * samplesPerBlock; | ||||
|                 m = (dataLen % blockAlign); | ||||
|         } else { | ||||
|                 n = 0; | ||||
|                 m = blockAlign; | ||||
|         } | ||||
|         if (m >= (size_t)(7*chans)) { | ||||
|                 m -= 7*chans;          /* bytes beyond block-header */ | ||||
|                 m = (2*m)/chans + 2;   /* nibbles/chans + 2 in header */ | ||||
|                 if (samplesPerBlock && m > samplesPerBlock) m = samplesPerBlock; | ||||
|                 n += m; | ||||
|         } | ||||
|         return n; | ||||
| } | ||||
| 
 | ||||
| size_t lsx_ms_adpcm_bytes_per_block( | ||||
|         size_t chans, | ||||
|         size_t samplesPerBlock | ||||
| ) | ||||
| { | ||||
|         size_t n; | ||||
|         n = 7*chans;  /* header */ | ||||
|         if (samplesPerBlock > 2) | ||||
|                 n += (((size_t)samplesPerBlock-2)*chans + 1)/2; | ||||
|         return n; | ||||
| } | ||||
| 
 | ||||
| @ -1,79 +0,0 @@ | ||||
| /* adpcm.h  codex functions for MS_ADPCM data
 | ||||
|  *          (hopefully) provides interoperability with | ||||
|  *          Microsoft's ADPCM format, but, as usual, | ||||
|  *          see LACK-OF-WARRANTY information below. | ||||
|  * | ||||
|  *      Copyright (C) 1999 Stanley J. Brooks <stabro@megsinet.net> | ||||
|  * | ||||
|  * This library is free software; you can redistribute it and/or modify it | ||||
|  * under the terms of the GNU Lesser General Public License as published by | ||||
|  * the Free Software Foundation; either version 2.1 of the License, or (at | ||||
|  * your option) any later version. | ||||
|  * | ||||
|  * This library is distributed in the hope that it will be useful, but | ||||
|  * WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser | ||||
|  * General Public License for more details. | ||||
|  * | ||||
|  * You should have received a copy of the GNU Lesser General Public License | ||||
|  * along with this library; if not, write to the Free Software Foundation, | ||||
|  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA | ||||
|  * | ||||
|  */ | ||||
| #include "sox.h" | ||||
| 
 | ||||
| #ifndef SAMPL | ||||
| #define SAMPL short | ||||
| #endif | ||||
| 
 | ||||
| /* default coef sets */ | ||||
| extern const short lsx_ms_adpcm_i_coef[7][2]; | ||||
| 
 | ||||
| extern void *lsx_ms_adpcm_alloc(unsigned chans); | ||||
| 
 | ||||
| /* lsx_ms_adpcm_block_expand_i() outputs interleaved samples into one output buffer */ | ||||
| extern const char *lsx_ms_adpcm_block_expand_i( | ||||
| 	void *priv, | ||||
| 	unsigned chans,          /* total channels             */ | ||||
| 	int nCoef, | ||||
| 	const short *coef, | ||||
| 	const unsigned char *ibuff,/* input buffer[blockAlign]   */ | ||||
| 	SAMPL *obuff,       /* output samples, n*chans    */ | ||||
| 	int n               /* samples to decode PER channel, REQUIRE n % 8 == 1  */ | ||||
| ); | ||||
| 
 | ||||
| extern void lsx_ms_adpcm_block_mash_i( | ||||
| 	unsigned chans,          /* total channels */ | ||||
| 	const SAMPL *ip,    /* ip[n*chans] is interleaved input samples */ | ||||
| 	int n,              /* samples to encode PER channel, REQUIRE */ | ||||
| 	int *st,            /* input/output steps, 16<=st[i] */ | ||||
| 	unsigned char *obuff,      /* output buffer[blockAlign] */ | ||||
| 	int blockAlign      /* >= 7*chans + n/2          */ | ||||
| ); | ||||
| 
 | ||||
| /* Some helper functions for computing samples/block and blockalign */ | ||||
| 
 | ||||
| /*
 | ||||
|  * lsx_ms_adpcm_samples_in(dataLen, chans, blockAlign, samplesPerBlock) | ||||
|  *  returns the number of samples/channel which would be | ||||
|  *  in the dataLen, given the other parameters ... | ||||
|  *  if input samplesPerBlock is 0, then returns the max | ||||
|  *  samplesPerBlock which would go into a block of size blockAlign | ||||
|  *  Yes, it is confusing usage. | ||||
|  */ | ||||
| extern size_t lsx_ms_adpcm_samples_in( | ||||
| 	size_t dataLen, | ||||
| 	size_t chans, | ||||
| 	size_t blockAlign, | ||||
| 	size_t samplesPerBlock | ||||
| ); | ||||
| 
 | ||||
| /*
 | ||||
|  * size_t lsx_ms_adpcm_bytes_per_block(chans, samplesPerBlock) | ||||
|  *   return minimum blocksize which would be required | ||||
|  *   to encode number of chans with given samplesPerBlock | ||||
|  */ | ||||
| extern size_t lsx_ms_adpcm_bytes_per_block( | ||||
| 	size_t chans, | ||||
| 	size_t samplesPerBlock | ||||
| ); | ||||
| @ -1,163 +0,0 @@ | ||||
| /* libSoX effect: Delay one or more channels (c) 2008 robs@users.sourceforge.net
 | ||||
|  * | ||||
|  * This library is free software; you can redistribute it and/or modify it | ||||
|  * under the terms of the GNU Lesser General Public License as published by | ||||
|  * the Free Software Foundation; either version 2.1 of the License, or (at | ||||
|  * your option) any later version. | ||||
|  * | ||||
|  * This library is distributed in the hope that it will be useful, but | ||||
|  * WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser | ||||
|  * General Public License for more details. | ||||
|  * | ||||
|  * You should have received a copy of the GNU Lesser General Public License | ||||
|  * along with this library; if not, write to the Free Software Foundation, | ||||
|  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA | ||||
|  */ | ||||
| 
 | ||||
| #include "sox_i.h" | ||||
| #include <string.h> | ||||
| 
 | ||||
| typedef struct { | ||||
|   size_t argc; | ||||
|   struct { char *str; uint64_t delay; } *args; | ||||
|   uint64_t *max_delay; | ||||
|   uint64_t delay, pre_pad, pad; | ||||
|   size_t buffer_size, buffer_index; | ||||
|   sox_sample_t * buffer; | ||||
|   sox_bool drain_started; | ||||
| } priv_t; | ||||
| 
 | ||||
| static int lsx_kill(sox_effect_t * effp) | ||||
| { | ||||
|   priv_t * p = (priv_t *)effp->priv; | ||||
|   unsigned i; | ||||
| 
 | ||||
|   for (i = 0; i < p->argc; ++i) | ||||
|     free(p->args[i].str); | ||||
|   free(p->args); | ||||
|   free(p->max_delay); | ||||
|   return SOX_SUCCESS; | ||||
| } | ||||
| 
 | ||||
| static int create(sox_effect_t * effp, int argc, char * * argv) | ||||
| { | ||||
|   priv_t * p = (priv_t *)effp->priv; | ||||
|   unsigned i; | ||||
| 
 | ||||
|   --argc, ++argv; | ||||
|   p->argc = argc; | ||||
|   p->args = lsx_calloc(p->argc, sizeof(*p->args)); | ||||
|   p->max_delay = lsx_malloc(sizeof(*p->max_delay)); | ||||
|   for (i = 0; i < p->argc; ++i) { | ||||
|     char const * next = lsx_parseposition(0., p->args[i].str = lsx_strdup(argv[i]), NULL, (uint64_t)0, (uint64_t)0, '='); | ||||
|     if (!next || *next) { | ||||
|       lsx_kill(effp); | ||||
|       return lsx_usage(effp); | ||||
|     } | ||||
|   } | ||||
|   return SOX_SUCCESS; | ||||
| } | ||||
| 
 | ||||
| static int stop(sox_effect_t * effp) | ||||
| { | ||||
|   priv_t * p = (priv_t *)effp->priv; | ||||
|   free(p->buffer); | ||||
|   return SOX_SUCCESS; | ||||
| } | ||||
| 
 | ||||
| static int start(sox_effect_t * effp) | ||||
| { | ||||
|   priv_t * p = (priv_t *)effp->priv; | ||||
|   uint64_t max_delay = 0, last_seen = 0, delay; | ||||
|   uint64_t in_length = effp->in_signal.length != SOX_UNKNOWN_LEN ? | ||||
|     effp->in_signal.length / effp->in_signal.channels : SOX_UNKNOWN_LEN; | ||||
| 
 | ||||
|   if (effp->flow == 0) { | ||||
|     unsigned i; | ||||
|     if (p->argc > effp->in_signal.channels) { | ||||
|       lsx_fail("too few input channels"); | ||||
|       return SOX_EOF; | ||||
|     } | ||||
|     for (i = 0; i < p->argc; ++i) { | ||||
|       if (!lsx_parseposition(effp->in_signal.rate, p->args[i].str, &delay, last_seen, in_length, '=') || delay == SOX_UNKNOWN_LEN) { | ||||
|         lsx_fail("Position relative to end of audio specified, but audio length is unknown"); | ||||
|         return SOX_EOF; | ||||
|       } | ||||
|       p->args[i].delay = last_seen = delay; | ||||
|       if (delay > max_delay) { | ||||
|         max_delay = delay; | ||||
|       } | ||||
|     } | ||||
|     *p->max_delay = max_delay; | ||||
|     if (max_delay == 0) | ||||
|       return SOX_EFF_NULL; | ||||
|     effp->out_signal.length = effp->in_signal.length != SOX_UNKNOWN_LEN ? | ||||
|        effp->in_signal.length + max_delay * effp->in_signal.channels : | ||||
|        SOX_UNKNOWN_LEN; | ||||
|     lsx_debug("extending audio by %" PRIu64 " samples", max_delay); | ||||
|   } | ||||
| 
 | ||||
|   max_delay = *p->max_delay; | ||||
|   if (effp->flow < p->argc) | ||||
|     p->buffer_size = p->args[effp->flow].delay; | ||||
|   p->buffer_index = p->delay = p->pre_pad = 0; | ||||
|   p->pad = max_delay - p->buffer_size; | ||||
|   p->buffer = lsx_malloc(p->buffer_size * sizeof(*p->buffer)); | ||||
|   p->drain_started = sox_false; | ||||
|   return SOX_SUCCESS; | ||||
| } | ||||
| 
 | ||||
| static int flow(sox_effect_t * effp, const sox_sample_t * ibuf, | ||||
|     sox_sample_t * obuf, size_t * isamp, size_t * osamp) | ||||
| { | ||||
|   priv_t * p = (priv_t *)effp->priv; | ||||
|   size_t len = *isamp = *osamp = min(*isamp, *osamp); | ||||
| 
 | ||||
|   if (!p->buffer_size) | ||||
|     memcpy(obuf, ibuf, len * sizeof(*obuf)); | ||||
|   else for (; len; --len) { | ||||
|     if (p->delay < p->buffer_size) { | ||||
|       p->buffer[p->delay++] = *ibuf++; | ||||
|       *obuf++ = 0; | ||||
|     } else { | ||||
|       *obuf++ = p->buffer[p->buffer_index]; | ||||
|       p->buffer[p->buffer_index++] = *ibuf++; | ||||
|       p->buffer_index %= p->buffer_size; | ||||
|     } | ||||
|   } | ||||
|   return SOX_SUCCESS; | ||||
| } | ||||
| 
 | ||||
| static int drain(sox_effect_t * effp, sox_sample_t * obuf, size_t * osamp) | ||||
| { | ||||
|   priv_t * p = (priv_t *)effp->priv; | ||||
|   size_t len; | ||||
|   if (! p->drain_started) { | ||||
|     p->drain_started = sox_true; | ||||
|     p->pre_pad = p->buffer_size - p->delay; | ||||
|       /* If the input was too short to fill the buffer completely,
 | ||||
|          flow() has not yet output enough silence to reach the | ||||
|          desired delay. */ | ||||
|   } | ||||
|   len = *osamp = min(p->pre_pad + p->delay + p->pad, *osamp); | ||||
| 
 | ||||
|   for (; p->pre_pad && len; --p->pre_pad, --len) | ||||
|     *obuf++ = 0; | ||||
|   for (; p->delay && len; --p->delay, --len) { | ||||
|     *obuf++ = p->buffer[p->buffer_index++]; | ||||
|     p->buffer_index %= p->buffer_size; | ||||
|   } | ||||
|   for (; p->pad && len; --p->pad, --len) | ||||
|     *obuf++ = 0; | ||||
|   return SOX_SUCCESS; | ||||
| } | ||||
| 
 | ||||
| sox_effect_handler_t const * lsx_delay_effect_fn(void) | ||||
| { | ||||
|   static sox_effect_handler_t handler = { | ||||
|     "delay", "{position}", SOX_EFF_LENGTH | SOX_EFF_MODIFY, | ||||
|     create, start, flow, drain, stop, lsx_kill, sizeof(priv_t) | ||||
|   }; | ||||
|   return &handler; | ||||
| } | ||||
| @ -1,85 +0,0 @@ | ||||
| /* libSoX effect: Downsample
 | ||||
|  * | ||||
|  * First version of this effect written 11/2011 by Ulrich Klauer. | ||||
|  * | ||||
|  * Copyright 2011 Chris Bagwell and SoX Contributors | ||||
|  * | ||||
|  * This library is free software; you can redistribute it and/or modify it | ||||
|  * under the terms of the GNU Lesser General Public License as published by | ||||
|  * the Free Software Foundation; either version 2.1 of the License, or (at | ||||
|  * your option) any later version. | ||||
|  * | ||||
|  * This library is distributed in the hope that it will be useful, but | ||||
|  * WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser | ||||
|  * General Public License for more details. | ||||
|  * | ||||
|  * You should have received a copy of the GNU Lesser General Public License | ||||
|  * along with this library; if not, write to the Free Software Foundation, | ||||
|  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA | ||||
|  */ | ||||
| 
 | ||||
| #include "sox_i.h" | ||||
| 
 | ||||
| typedef struct { | ||||
|   unsigned int factor; | ||||
|   unsigned int carry; /* number of samples still to be discarded,
 | ||||
|                          carried over from last block */ | ||||
| } priv_t; | ||||
| 
 | ||||
| static int create(sox_effect_t *effp, int argc, char **argv) | ||||
| { | ||||
|   priv_t *p = (priv_t*)effp->priv; | ||||
|   p->factor = 2; | ||||
|   --argc, ++argv; | ||||
|   do { /* break-able block */ | ||||
|     NUMERIC_PARAMETER(factor, 1, 16384) | ||||
|   } while (0); | ||||
|   return argc ? lsx_usage(effp) : SOX_SUCCESS; | ||||
| } | ||||
| 
 | ||||
| static int start(sox_effect_t *effp) | ||||
| { | ||||
|   priv_t *p = (priv_t*) effp->priv; | ||||
|   effp->out_signal.rate = effp->in_signal.rate / p->factor; | ||||
|   return p->factor == 1 ? SOX_EFF_NULL : SOX_SUCCESS; | ||||
| } | ||||
| 
 | ||||
| static int flow(sox_effect_t *effp, const sox_sample_t *ibuf, | ||||
|     sox_sample_t *obuf, size_t *isamp, size_t *osamp) | ||||
| { | ||||
|   priv_t *p = (priv_t*)effp->priv; | ||||
|   size_t ilen = *isamp, olen = *osamp; | ||||
|   size_t t; | ||||
| 
 | ||||
|   t = min(p->carry, ilen); | ||||
|   p->carry -= t; | ||||
|   ibuf += t; ilen -= t; | ||||
| 
 | ||||
|   /* NB: either p->carry (usually) or ilen is now zero; hence, a
 | ||||
|      non-zero value of ilen implies p->carry == 0, and there is no | ||||
|      need to test for this in the following while and if. */ | ||||
| 
 | ||||
|   while (ilen >= p->factor && olen) { | ||||
|     *obuf++ = *ibuf; | ||||
|     ibuf += p->factor; | ||||
|     olen--; ilen -= p->factor; | ||||
|   } | ||||
| 
 | ||||
|   if (ilen && olen) { | ||||
|     *obuf++ = *ibuf; | ||||
|     p->carry = p->factor - ilen; | ||||
|     olen--; ilen = 0; | ||||
|   } | ||||
| 
 | ||||
|   *isamp -= ilen, *osamp -= olen; | ||||
|   return SOX_SUCCESS; | ||||
| } | ||||
| 
 | ||||
| sox_effect_handler_t const *lsx_downsample_effect_fn(void) | ||||
| { | ||||
|   static sox_effect_handler_t handler = {"downsample", "[factor (2)]", | ||||
|     SOX_EFF_RATE | SOX_EFF_MODIFY, | ||||
|     create, start, flow, NULL, NULL, NULL, sizeof(priv_t)}; | ||||
|   return &handler; | ||||
| } | ||||
| @ -1,266 +0,0 @@ | ||||
| /* libSoX Echo effect             August 24, 1998
 | ||||
|  * | ||||
|  * Copyright (C) 1998 Juergen Mueller And Sundry Contributors | ||||
|  * This source code is freely redistributable and may be used for | ||||
|  * any purpose.  This copyright notice must be maintained. | ||||
|  * Juergen Mueller And Sundry Contributors are not responsible for | ||||
|  * the consequences of using this software. | ||||
|  * | ||||
|  * | ||||
|  * Flow diagram scheme for n delays ( 1 <= n <= MAX_ECHOS ): | ||||
|  * | ||||
|  *        * gain-in                                              ___ | ||||
|  * ibuff -----------+------------------------------------------>|   | | ||||
|  *                  |       _________                           |   | | ||||
|  *                  |      |         |                * decay 1 |   | | ||||
|  *                  +----->| delay 1 |------------------------->|   | | ||||
|  *                  |      |_________|                          |   | | ||||
|  *                  |            _________                      | + | | ||||
|  *                  |           |         |           * decay 2 |   | | ||||
|  *                  +---------->| delay 2 |-------------------->|   | | ||||
|  *                  |           |_________|                     |   | | ||||
|  *                  :                 _________                 |   | | ||||
|  *                  |                |         |      * decay n |   | | ||||
|  *                  +--------------->| delay n |--------------->|___| | ||||
|  *                                   |_________|                  | | ||||
|  *                                                                | * gain-out | ||||
|  *                                                                | | ||||
|  *                                                                +----->obuff | ||||
|  * Usage: | ||||
|  *   echo gain-in gain-out delay-1 decay-1 [delay-2 decay-2 ... delay-n decay-n] | ||||
|  * | ||||
|  * Where: | ||||
|  *   gain-in, decay-1 ... decay-n :  0.0 ... 1.0      volume | ||||
|  *   gain-out :  0.0 ...      volume | ||||
|  *   delay-1 ... delay-n :  > 0.0 msec | ||||
|  * | ||||
|  * Note: | ||||
|  *   when decay is close to 1.0, the samples can begin clipping and the output | ||||
|  *   can saturate! | ||||
|  * | ||||
|  * Hint: | ||||
|  *   1 / out-gain > gain-in ( 1 + decay-1 + ... + decay-n ) | ||||
|  */ | ||||
| 
 | ||||
| #include "sox_i.h" | ||||
| 
 | ||||
| #include <stdlib.h> /* Harmless, and prototypes atof() etc. --dgc */ | ||||
| 
 | ||||
| #define DELAY_BUFSIZ ( 50 * 50U * 1024 ) | ||||
| #define MAX_ECHOS 7     /* 24 bit x ( 1 + MAX_ECHOS ) = */ | ||||
|                         /* 24 bit x 8 = 32 bit !!!      */ | ||||
| 
 | ||||
| /* Private data for SKEL file */ | ||||
| typedef struct { | ||||
|         int     counter; | ||||
|         int     num_delays; | ||||
|         double  *delay_buf; | ||||
|         float   in_gain, out_gain; | ||||
|         float   delay[MAX_ECHOS], decay[MAX_ECHOS]; | ||||
|         ptrdiff_t samples[MAX_ECHOS], maxsamples; | ||||
|         size_t fade_out; | ||||
| } priv_t; | ||||
| 
 | ||||
| /* Private data for SKEL file */ | ||||
| 
 | ||||
| 
 | ||||
| /*
 | ||||
|  * Process options | ||||
|  */ | ||||
| static int sox_echo_getopts(sox_effect_t * effp, int argc, char **argv) | ||||
| { | ||||
|         priv_t * echo = (priv_t *) effp->priv; | ||||
|         int i; | ||||
| 
 | ||||
|   --argc, ++argv; | ||||
|         echo->num_delays = 0; | ||||
| 
 | ||||
|         if ((argc < 4) || (argc % 2)) | ||||
|           return lsx_usage(effp); | ||||
| 
 | ||||
|         i = 0; | ||||
|         sscanf(argv[i++], "%f", &echo->in_gain); | ||||
|         sscanf(argv[i++], "%f", &echo->out_gain); | ||||
|         while (i < argc) { | ||||
|                 if ( echo->num_delays >= MAX_ECHOS ) | ||||
|                         lsx_fail("echo: to many delays, use less than %i delays", | ||||
|                                 MAX_ECHOS); | ||||
|                 /* Linux bug and it's cleaner. */ | ||||
|                 sscanf(argv[i++], "%f", &echo->delay[echo->num_delays]); | ||||
|                 sscanf(argv[i++], "%f", &echo->decay[echo->num_delays]); | ||||
|                 echo->num_delays++; | ||||
|         } | ||||
|         return (SOX_SUCCESS); | ||||
| } | ||||
| 
 | ||||
| /*
 | ||||
|  * Prepare for processing. | ||||
|  */ | ||||
| static int sox_echo_start(sox_effect_t * effp) | ||||
| { | ||||
|         priv_t * echo = (priv_t *) effp->priv; | ||||
|         int i; | ||||
|         float sum_in_volume; | ||||
|         long j; | ||||
| 
 | ||||
|         echo->maxsamples = 0; | ||||
|         if ( echo->in_gain < 0.0 ) | ||||
|         { | ||||
|                 lsx_fail("echo: gain-in must be positive!"); | ||||
|                 return (SOX_EOF); | ||||
|         } | ||||
|         if ( echo->in_gain > 1.0 ) | ||||
|         { | ||||
|                 lsx_fail("echo: gain-in must be less than 1.0!"); | ||||
|                 return (SOX_EOF); | ||||
|         } | ||||
|         if ( echo->out_gain < 0.0 ) | ||||
|         { | ||||
|                 lsx_fail("echo: gain-in must be positive!"); | ||||
|                 return (SOX_EOF); | ||||
|         } | ||||
|         for ( i = 0; i < echo->num_delays; i++ ) { | ||||
|                 echo->samples[i] = echo->delay[i] * effp->in_signal.rate / 1000.0; | ||||
|                 if ( echo->samples[i] < 1 ) | ||||
|                 { | ||||
|                     lsx_fail("echo: delay must be positive!"); | ||||
|                     return (SOX_EOF); | ||||
|                 } | ||||
|                 if ( echo->samples[i] > (ptrdiff_t)DELAY_BUFSIZ ) | ||||
|                 { | ||||
|                         lsx_fail("echo: delay must be less than %g seconds!", | ||||
|                                 DELAY_BUFSIZ / effp->in_signal.rate ); | ||||
|                         return (SOX_EOF); | ||||
|                 } | ||||
|                 if ( echo->decay[i] < 0.0 ) | ||||
|                 { | ||||
|                     lsx_fail("echo: decay must be positive!" ); | ||||
|                     return (SOX_EOF); | ||||
|                 } | ||||
|                 if ( echo->decay[i] > 1.0 ) | ||||
|                 { | ||||
|                     lsx_fail("echo: decay must be less than 1.0!" ); | ||||
|                     return (SOX_EOF); | ||||
|                 } | ||||
|                 if ( echo->samples[i] > echo->maxsamples ) | ||||
|                         echo->maxsamples = echo->samples[i]; | ||||
|         } | ||||
|         echo->delay_buf = lsx_malloc(sizeof (double) * echo->maxsamples); | ||||
|         for ( j = 0; j < echo->maxsamples; ++j ) | ||||
|                 echo->delay_buf[j] = 0.0; | ||||
|         /* Be nice and check the hint with warning, if... */ | ||||
|         sum_in_volume = 1.0; | ||||
|         for ( i = 0; i < echo->num_delays; i++ ) | ||||
|                 sum_in_volume += echo->decay[i]; | ||||
|         if ( sum_in_volume * echo->in_gain > 1.0 / echo->out_gain ) | ||||
|                 lsx_warn("echo: warning >>> gain-out can cause saturation of output <<<"); | ||||
|         echo->counter = 0; | ||||
|         echo->fade_out = echo->maxsamples; | ||||
| 
 | ||||
|   effp->out_signal.length = SOX_UNKNOWN_LEN; /* TODO: calculate actual length */ | ||||
| 
 | ||||
|         return (SOX_SUCCESS); | ||||
| } | ||||
| 
 | ||||
| /*
 | ||||
|  * Processed signed long samples from ibuf to obuf. | ||||
|  * Return number of samples processed. | ||||
|  */ | ||||
| static int sox_echo_flow(sox_effect_t * effp, const sox_sample_t *ibuf, sox_sample_t *obuf, | ||||
|                  size_t *isamp, size_t *osamp) | ||||
| { | ||||
|         priv_t * echo = (priv_t *) effp->priv; | ||||
|         int j; | ||||
|         double d_in, d_out; | ||||
|         sox_sample_t out; | ||||
|         size_t len = min(*isamp, *osamp); | ||||
|         *isamp = *osamp = len; | ||||
| 
 | ||||
|         while (len--) { | ||||
|                 /* Store delays as 24-bit signed longs */ | ||||
|                 d_in = (double) *ibuf++ / 256; | ||||
|                 /* Compute output first */ | ||||
|                 d_out = d_in * echo->in_gain; | ||||
|                 for ( j = 0; j < echo->num_delays; j++ ) { | ||||
|                         d_out += echo->delay_buf[ | ||||
| (echo->counter + echo->maxsamples - echo->samples[j]) % echo->maxsamples] | ||||
|                         * echo->decay[j]; | ||||
|                 } | ||||
|                 /* Adjust the output volume and size to 24 bit */ | ||||
|                 d_out = d_out * echo->out_gain; | ||||
|                 out = SOX_24BIT_CLIP_COUNT((sox_sample_t) d_out, effp->clips); | ||||
|                 *obuf++ = out * 256; | ||||
|                 /* Store input in delay buffer */ | ||||
|                 echo->delay_buf[echo->counter] = d_in; | ||||
|                 /* Adjust the counter */ | ||||
|                 echo->counter = ( echo->counter + 1 ) % echo->maxsamples; | ||||
|         } | ||||
|         /* processed all samples */ | ||||
|         return (SOX_SUCCESS); | ||||
| } | ||||
| 
 | ||||
| /*
 | ||||
|  * Drain out reverb lines. | ||||
|  */ | ||||
| static int sox_echo_drain(sox_effect_t * effp, sox_sample_t *obuf, size_t *osamp) | ||||
| { | ||||
|         priv_t * echo = (priv_t *) effp->priv; | ||||
|         double d_in, d_out; | ||||
|         sox_sample_t out; | ||||
|         int j; | ||||
|         size_t done; | ||||
| 
 | ||||
|         done = 0; | ||||
|         /* drain out delay samples */ | ||||
|         while ( ( done < *osamp ) && ( done < echo->fade_out ) ) { | ||||
|                 d_in = 0; | ||||
|                 d_out = 0; | ||||
|                 for ( j = 0; j < echo->num_delays; j++ ) { | ||||
|                         d_out += echo->delay_buf[ | ||||
| (echo->counter + echo->maxsamples - echo->samples[j]) % echo->maxsamples] | ||||
|                         * echo->decay[j]; | ||||
|                 } | ||||
|                 /* Adjust the output volume and size to 24 bit */ | ||||
|                 d_out = d_out * echo->out_gain; | ||||
|                 out = SOX_24BIT_CLIP_COUNT((sox_sample_t) d_out, effp->clips); | ||||
|                 *obuf++ = out * 256; | ||||
|                 /* Store input in delay buffer */ | ||||
|                 echo->delay_buf[echo->counter] = d_in; | ||||
|                 /* Adjust the counters */ | ||||
|                 echo->counter = ( echo->counter + 1 ) % echo->maxsamples; | ||||
|                 done++; | ||||
|                 echo->fade_out--; | ||||
|         }; | ||||
|         /* samples played, it remains */ | ||||
|         *osamp = done; | ||||
|         if (echo->fade_out == 0) | ||||
|             return SOX_EOF; | ||||
|         else | ||||
|             return SOX_SUCCESS; | ||||
| } | ||||
| 
 | ||||
| static int sox_echo_stop(sox_effect_t * effp) | ||||
| { | ||||
|         priv_t * echo = (priv_t *) effp->priv; | ||||
| 
 | ||||
|         free(echo->delay_buf); | ||||
|         echo->delay_buf = NULL; | ||||
|         return (SOX_SUCCESS); | ||||
| } | ||||
| 
 | ||||
| static sox_effect_handler_t sox_echo_effect = { | ||||
|   "echo", | ||||
|   "gain-in gain-out delay decay [ delay decay ... ]", | ||||
|   SOX_EFF_LENGTH | SOX_EFF_GAIN, | ||||
|   sox_echo_getopts, | ||||
|   sox_echo_start, | ||||
|   sox_echo_flow, | ||||
|   sox_echo_drain, | ||||
|   sox_echo_stop, | ||||
|   NULL, sizeof(priv_t) | ||||
| }; | ||||
| 
 | ||||
| const sox_effect_handler_t *lsx_echo_effect_fn(void) | ||||
| { | ||||
|     return &sox_echo_effect; | ||||
| } | ||||
| @ -1,278 +0,0 @@ | ||||
| /* libSoX Echo effect             August 24, 1998
 | ||||
|  * | ||||
|  * Copyright (C) 1998 Juergen Mueller And Sundry Contributors | ||||
|  * This source code is freely redistributable and may be used for | ||||
|  * any purpose.  This copyright notice must be maintained. | ||||
|  * Juergen Mueller And Sundry Contributors are not responsible for | ||||
|  * the consequences of using this software. | ||||
|  * | ||||
|  * | ||||
|  * Flow diagram scheme for n delays ( 1 <= n <= MAX_ECHOS ): | ||||
|  * | ||||
|  *                                                    * gain-in  ___ | ||||
|  * ibuff --+--------------------------------------------------->|   | | ||||
|  *         |                                          * decay 1 |   | | ||||
|  *         |               +----------------------------------->|   | | ||||
|  *         |               |                          * decay 2 | + | | ||||
|  *         |               |             +--------------------->|   | | ||||
|  *         |               |             |            * decay n |   | | ||||
|  *         |    _________  |  _________  |     _________   +--->|___| | ||||
|  *         |   |         | | |         | |    |         |  |      | | ||||
|  *         +-->| delay 1 |-+-| delay 2 |-+...-| delay n |--+      | * gain-out | ||||
|  *             |_________|   |_________|      |_________|         | | ||||
|  *                                                                +----->obuff | ||||
|  * Usage: | ||||
|  *   echos gain-in gain-out delay-1 decay-1 [delay-2 decay-2 ... delay-n decay-n] | ||||
|  * | ||||
|  * Where: | ||||
|  *   gain-in, decay-1 ... decay-n :  0.0 ... 1.0      volume | ||||
|  *   gain-out :  0.0 ...      volume | ||||
|  *   delay-1 ... delay-n :  > 0.0 msec | ||||
|  * | ||||
|  * Note: | ||||
|  *   when decay is close to 1.0, the samples can begin clipping and the output | ||||
|  *   can saturate! | ||||
|  * | ||||
|  * Hint: | ||||
|  *   1 / out-gain > gain-in ( 1 + decay-1 + ... + decay-n ) | ||||
|  * | ||||
|  */ | ||||
| 
 | ||||
| #include "sox_i.h" | ||||
| 
 | ||||
| #include <stdlib.h> /* Harmless, and prototypes atof() etc. --dgc */ | ||||
| 
 | ||||
| #define DELAY_BUFSIZ ( 50 * 50U * 1024 ) | ||||
| #define MAX_ECHOS 7     /* 24 bit x ( 1 + MAX_ECHOS ) = */ | ||||
|                         /* 24 bit x 8 = 32 bit !!!      */ | ||||
| 
 | ||||
| /* Private data for SKEL file */ | ||||
| typedef struct { | ||||
|         int     counter[MAX_ECHOS]; | ||||
|         int     num_delays; | ||||
|         double  *delay_buf; | ||||
|         float   in_gain, out_gain; | ||||
|         float   delay[MAX_ECHOS], decay[MAX_ECHOS]; | ||||
|         ptrdiff_t samples[MAX_ECHOS], pointer[MAX_ECHOS]; | ||||
|         size_t sumsamples; | ||||
| } priv_t; | ||||
| 
 | ||||
| /* Private data for SKEL file */ | ||||
| 
 | ||||
| /*
 | ||||
|  * Process options | ||||
|  */ | ||||
| static int sox_echos_getopts(sox_effect_t * effp, int argc, char **argv) | ||||
| { | ||||
|         priv_t * echos = (priv_t *) effp->priv; | ||||
|         int i; | ||||
| 
 | ||||
|         echos->num_delays = 0; | ||||
| 
 | ||||
|   --argc, ++argv; | ||||
|         if ((argc < 4) || (argc % 2)) | ||||
|           return lsx_usage(effp); | ||||
| 
 | ||||
|         i = 0; | ||||
|         sscanf(argv[i++], "%f", &echos->in_gain); | ||||
|         sscanf(argv[i++], "%f", &echos->out_gain); | ||||
|         while (i < argc) { | ||||
|                 /* Linux bug and it's cleaner. */ | ||||
|                 sscanf(argv[i++], "%f", &echos->delay[echos->num_delays]); | ||||
|                 sscanf(argv[i++], "%f", &echos->decay[echos->num_delays]); | ||||
|                 echos->num_delays++; | ||||
|                 if ( echos->num_delays > MAX_ECHOS ) | ||||
|                 { | ||||
|                         lsx_fail("echos: to many delays, use less than %i delays", | ||||
|                                 MAX_ECHOS); | ||||
|                         return (SOX_EOF); | ||||
|                 } | ||||
|         } | ||||
|         echos->sumsamples = 0; | ||||
|         return (SOX_SUCCESS); | ||||
| } | ||||
| 
 | ||||
| /*
 | ||||
|  * Prepare for processing. | ||||
|  */ | ||||
| static int sox_echos_start(sox_effect_t * effp) | ||||
| { | ||||
|         priv_t * echos = (priv_t *) effp->priv; | ||||
|         int i; | ||||
|         float sum_in_volume; | ||||
|         unsigned long j; | ||||
| 
 | ||||
|         if ( echos->in_gain < 0.0 ) | ||||
|         { | ||||
|                 lsx_fail("echos: gain-in must be positive!"); | ||||
|                 return (SOX_EOF); | ||||
|         } | ||||
|         if ( echos->in_gain > 1.0 ) | ||||
|         { | ||||
|                 lsx_fail("echos: gain-in must be less than 1.0!"); | ||||
|                 return (SOX_EOF); | ||||
|         } | ||||
|         if ( echos->out_gain < 0.0 ) | ||||
|         { | ||||
|                 lsx_fail("echos: gain-in must be positive!"); | ||||
|                 return (SOX_EOF); | ||||
|         } | ||||
|         for ( i = 0; i < echos->num_delays; i++ ) { | ||||
|                 echos->samples[i] = echos->delay[i] * effp->in_signal.rate / 1000.0; | ||||
|                 if ( echos->samples[i] < 1 ) | ||||
|                 { | ||||
|                     lsx_fail("echos: delay must be positive!"); | ||||
|                     return (SOX_EOF); | ||||
|                 } | ||||
|                 if ( echos->samples[i] > (ptrdiff_t)DELAY_BUFSIZ ) | ||||
|                 { | ||||
|                         lsx_fail("echos: delay must be less than %g seconds!", | ||||
|                                 DELAY_BUFSIZ / effp->in_signal.rate ); | ||||
|                         return (SOX_EOF); | ||||
|                 } | ||||
|                 if ( echos->decay[i] < 0.0 ) | ||||
|                 { | ||||
|                     lsx_fail("echos: decay must be positive!" ); | ||||
|                     return (SOX_EOF); | ||||
|                 } | ||||
|                 if ( echos->decay[i] > 1.0 ) | ||||
|                 { | ||||
|                     lsx_fail("echos: decay must be less than 1.0!" ); | ||||
|                     return (SOX_EOF); | ||||
|                 } | ||||
|                 echos->counter[i] = 0; | ||||
|                 echos->pointer[i] = echos->sumsamples; | ||||
|                 echos->sumsamples += echos->samples[i]; | ||||
|         } | ||||
|         echos->delay_buf = lsx_malloc(sizeof (double) * echos->sumsamples); | ||||
|         for ( j = 0; j < echos->sumsamples; ++j ) | ||||
|                 echos->delay_buf[j] = 0.0; | ||||
|         /* Be nice and check the hint with warning, if... */ | ||||
|         sum_in_volume = 1.0; | ||||
|         for ( i = 0; i < echos->num_delays; i++ ) | ||||
|                 sum_in_volume += echos->decay[i]; | ||||
|         if ( sum_in_volume * echos->in_gain > 1.0 / echos->out_gain ) | ||||
|                 lsx_warn("echos: warning >>> gain-out can cause saturation of output <<<"); | ||||
| 
 | ||||
|   effp->out_signal.length = SOX_UNKNOWN_LEN; /* TODO: calculate actual length */ | ||||
| 
 | ||||
|         return (SOX_SUCCESS); | ||||
| } | ||||
| 
 | ||||
| /*
 | ||||
|  * Processed signed long samples from ibuf to obuf. | ||||
|  * Return number of samples processed. | ||||
|  */ | ||||
| static int sox_echos_flow(sox_effect_t * effp, const sox_sample_t *ibuf, sox_sample_t *obuf, | ||||
|                 size_t *isamp, size_t *osamp) | ||||
| { | ||||
|         priv_t * echos = (priv_t *) effp->priv; | ||||
|         int j; | ||||
|         double d_in, d_out; | ||||
|         sox_sample_t out; | ||||
|         size_t len = min(*isamp, *osamp); | ||||
|         *isamp = *osamp = len; | ||||
| 
 | ||||
|         while (len--) { | ||||
|                 /* Store delays as 24-bit signed longs */ | ||||
|                 d_in = (double) *ibuf++ / 256; | ||||
|                 /* Compute output first */ | ||||
|                 d_out = d_in * echos->in_gain; | ||||
|                 for ( j = 0; j < echos->num_delays; j++ ) { | ||||
|                         d_out += echos->delay_buf[echos->counter[j] + echos->pointer[j]] * echos->decay[j]; | ||||
|                 } | ||||
|                 /* Adjust the output volume and size to 24 bit */ | ||||
|                 d_out = d_out * echos->out_gain; | ||||
|                 out = SOX_24BIT_CLIP_COUNT((sox_sample_t) d_out, effp->clips); | ||||
|                 *obuf++ = out * 256; | ||||
|                 /* Mix decay of delays and input */ | ||||
|                 for ( j = 0; j < echos->num_delays; j++ ) { | ||||
|                         if ( j == 0 ) | ||||
|                                 echos->delay_buf[echos->counter[j] + echos->pointer[j]] = d_in; | ||||
|                         else | ||||
|                                 echos->delay_buf[echos->counter[j] + echos->pointer[j]] = | ||||
|                                    echos->delay_buf[echos->counter[j-1] + echos->pointer[j-1]] + d_in; | ||||
|                 } | ||||
|                 /* Adjust the counters */ | ||||
|                 for ( j = 0; j < echos->num_delays; j++ ) | ||||
|                         echos->counter[j] = | ||||
|                            ( echos->counter[j] + 1 ) % echos->samples[j]; | ||||
|         } | ||||
|         /* processed all samples */ | ||||
|         return (SOX_SUCCESS); | ||||
| } | ||||
| 
 | ||||
| /*
 | ||||
|  * Drain out reverb lines. | ||||
|  */ | ||||
| static int sox_echos_drain(sox_effect_t * effp, sox_sample_t *obuf, size_t *osamp) | ||||
| { | ||||
|         priv_t * echos = (priv_t *) effp->priv; | ||||
|         double d_in, d_out; | ||||
|         sox_sample_t out; | ||||
|         int j; | ||||
|         size_t done; | ||||
| 
 | ||||
|         done = 0; | ||||
|         /* drain out delay samples */ | ||||
|         while ( ( done < *osamp ) && ( done < echos->sumsamples ) ) { | ||||
|                 d_in = 0; | ||||
|                 d_out = 0; | ||||
|                 for ( j = 0; j < echos->num_delays; j++ ) { | ||||
|                         d_out += echos->delay_buf[echos->counter[j] + echos->pointer[j]] * echos->decay[j]; | ||||
|                 } | ||||
|                 /* Adjust the output volume and size to 24 bit */ | ||||
|                 d_out = d_out * echos->out_gain; | ||||
|                 out = SOX_24BIT_CLIP_COUNT((sox_sample_t) d_out, effp->clips); | ||||
|                 *obuf++ = out * 256; | ||||
|                 /* Mix decay of delays and input */ | ||||
|                 for ( j = 0; j < echos->num_delays; j++ ) { | ||||
|                         if ( j == 0 ) | ||||
|                                 echos->delay_buf[echos->counter[j] + echos->pointer[j]] = d_in; | ||||
|                         else | ||||
|                                 echos->delay_buf[echos->counter[j] + echos->pointer[j]] = | ||||
|                                    echos->delay_buf[echos->counter[j-1] + echos->pointer[j-1]]; | ||||
|                 } | ||||
|                 /* Adjust the counters */ | ||||
|                 for ( j = 0; j < echos->num_delays; j++ ) | ||||
|                         echos->counter[j] = | ||||
|                            ( echos->counter[j] + 1 ) % echos->samples[j]; | ||||
|                 done++; | ||||
|                 echos->sumsamples--; | ||||
|         }; | ||||
|         /* samples played, it remains */ | ||||
|         *osamp = done; | ||||
|         if (echos->sumsamples == 0) | ||||
|             return SOX_EOF; | ||||
|         else | ||||
|             return SOX_SUCCESS; | ||||
| } | ||||
| 
 | ||||
| /*
 | ||||
|  * Clean up echos effect. | ||||
|  */ | ||||
| static int sox_echos_stop(sox_effect_t * effp) | ||||
| { | ||||
|         priv_t * echos = (priv_t *) effp->priv; | ||||
| 
 | ||||
|         free(echos->delay_buf); | ||||
|         echos->delay_buf = NULL; | ||||
|         return (SOX_SUCCESS); | ||||
| } | ||||
| 
 | ||||
| static sox_effect_handler_t sox_echos_effect = { | ||||
|   "echos", | ||||
|   "gain-in gain-out delay decay [ delay decay ... ]", | ||||
|   SOX_EFF_LENGTH | SOX_EFF_GAIN, | ||||
|   sox_echos_getopts, | ||||
|   sox_echos_start, | ||||
|   sox_echos_flow, | ||||
|   sox_echos_drain, | ||||
|   sox_echos_stop, | ||||
|   NULL, sizeof(priv_t) | ||||
| }; | ||||
| 
 | ||||
| const sox_effect_handler_t *lsx_echos_effect_fn(void) | ||||
| { | ||||
|     return &sox_echos_effect; | ||||
| } | ||||
| @ -1,669 +0,0 @@ | ||||
| /* SoX Effects chain     (c) 2007 robs@users.sourceforge.net
 | ||||
|  * | ||||
|  * This library is free software; you can redistribute it and/or modify it | ||||
|  * under the terms of the GNU Lesser General Public License as published by | ||||
|  * the Free Software Foundation; either version 2.1 of the License, or (at | ||||
|  * your option) any later version. | ||||
|  * | ||||
|  * This library is distributed in the hope that it will be useful, but | ||||
|  * WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser | ||||
|  * General Public License for more details. | ||||
|  * | ||||
|  * You should have received a copy of the GNU Lesser General Public License | ||||
|  * along with this library; if not, write to the Free Software Foundation, | ||||
|  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA | ||||
|  */ | ||||
| 
 | ||||
| #define LSX_EFF_ALIAS | ||||
| #include "sox_i.h" | ||||
| #include <assert.h> | ||||
| #include <string.h> | ||||
| #ifdef HAVE_STRINGS_H | ||||
|   #include <strings.h> | ||||
| #endif | ||||
| 
 | ||||
| #define DEBUG_EFFECTS_CHAIN 0 | ||||
| 
 | ||||
| /* Default effect handler functions for do-nothing situations: */ | ||||
| 
 | ||||
| static int default_function(sox_effect_t * effp UNUSED) | ||||
| { | ||||
|   return SOX_SUCCESS; | ||||
| } | ||||
| 
 | ||||
| /* Pass through samples verbatim */ | ||||
| int lsx_flow_copy(sox_effect_t * effp UNUSED, const sox_sample_t * ibuf, | ||||
|     sox_sample_t * obuf, size_t * isamp, size_t * osamp) | ||||
| { | ||||
|   *isamp = *osamp = min(*isamp, *osamp); | ||||
|   memcpy(obuf, ibuf, *isamp * sizeof(*obuf)); | ||||
|   return SOX_SUCCESS; | ||||
| } | ||||
| 
 | ||||
| /* Inform no more samples to drain */ | ||||
| static int default_drain(sox_effect_t * effp UNUSED, sox_sample_t *obuf UNUSED, size_t *osamp) | ||||
| { | ||||
|   *osamp = 0; | ||||
|   return SOX_EOF; | ||||
| } | ||||
| 
 | ||||
| /* Check that no parameters have been given */ | ||||
| static int default_getopts(sox_effect_t * effp, int argc, char **argv UNUSED) | ||||
| { | ||||
|   return --argc? lsx_usage(effp) : SOX_SUCCESS; | ||||
| } | ||||
| 
 | ||||
| /* Partially initialise the effect structure; signal info will come later */ | ||||
| sox_effect_t * sox_create_effect(sox_effect_handler_t const * eh) | ||||
| { | ||||
|   sox_effect_t * effp = lsx_calloc(1, sizeof(*effp)); | ||||
|   effp->obuf = NULL; | ||||
| 
 | ||||
|   effp->global_info = sox_get_effects_globals(); | ||||
|   effp->handler = *eh; | ||||
|   if (!effp->handler.getopts) effp->handler.getopts = default_getopts; | ||||
|   if (!effp->handler.start  ) effp->handler.start   = default_function; | ||||
|   if (!effp->handler.flow   ) effp->handler.flow    = lsx_flow_copy; | ||||
|   if (!effp->handler.drain  ) effp->handler.drain   = default_drain; | ||||
|   if (!effp->handler.stop   ) effp->handler.stop    = default_function; | ||||
|   if (!effp->handler.kill   ) effp->handler.kill    = default_function; | ||||
| 
 | ||||
|   effp->priv = lsx_calloc(1, effp->handler.priv_size); | ||||
| 
 | ||||
|   return effp; | ||||
| } /* sox_create_effect */ | ||||
| 
 | ||||
| int sox_effect_options(sox_effect_t *effp, int argc, char * const argv[]) | ||||
| { | ||||
|   int result; | ||||
| 
 | ||||
|   char * * argv2 = lsx_malloc((argc + 1) * sizeof(*argv2)); | ||||
|   argv2[0] = (char *)effp->handler.name; | ||||
|   memcpy(argv2 + 1, argv, argc * sizeof(*argv2)); | ||||
|   result = effp->handler.getopts(effp, argc + 1, argv2); | ||||
|   free(argv2); | ||||
|   return result; | ||||
| } /* sox_effect_options */ | ||||
| 
 | ||||
| /* Effects chain: */ | ||||
| 
 | ||||
| sox_effects_chain_t * sox_create_effects_chain( | ||||
|     sox_encodinginfo_t const * in_enc, sox_encodinginfo_t const * out_enc) | ||||
| { | ||||
|   sox_effects_chain_t * result = lsx_calloc(1, sizeof(sox_effects_chain_t)); | ||||
|   result->global_info = *sox_get_effects_globals(); | ||||
|   result->in_enc = in_enc; | ||||
|   result->out_enc = out_enc; | ||||
|   return result; | ||||
| } /* sox_create_effects_chain */ | ||||
| 
 | ||||
| void sox_delete_effects_chain(sox_effects_chain_t *ecp) | ||||
| { | ||||
|     if (ecp && ecp->length) | ||||
|         sox_delete_effects(ecp); | ||||
|     free(ecp->effects); | ||||
|     free(ecp); | ||||
| } /* sox_delete_effects_chain */ | ||||
| 
 | ||||
| /* Effect can call in start() or flow() to set minimum input size to flow() */ | ||||
| int lsx_effect_set_imin(sox_effect_t * effp, size_t imin) | ||||
| { | ||||
|   if (imin > sox_globals.bufsiz / effp->flows) { | ||||
|     lsx_fail("sox_bufsiz not big enough"); | ||||
|     return SOX_EOF; | ||||
|   } | ||||
| 
 | ||||
|   effp->imin = imin; | ||||
|   return SOX_SUCCESS; | ||||
| } | ||||
| 
 | ||||
| /* Effects table to be extended in steps of EFF_TABLE_STEP */ | ||||
| #define EFF_TABLE_STEP 8 | ||||
| 
 | ||||
| /* Add an effect to the chain. *in is the input signal for this effect. *out is
 | ||||
|  * a suggestion as to what the output signal should be, but depending on its | ||||
|  * given options and *in, the effect can choose to do differently.  Whatever | ||||
|  * output rate and channels the effect does produce are written back to *in, | ||||
|  * ready for the next effect in the chain. | ||||
|  */ | ||||
| int sox_add_effect(sox_effects_chain_t * chain, sox_effect_t * effp, sox_signalinfo_t * in, sox_signalinfo_t const * out) | ||||
| { | ||||
|   int ret, (*start)(sox_effect_t * effp) = effp->handler.start; | ||||
|   size_t f; | ||||
|   sox_effect_t eff0;  /* Copy of effect for flow 0 before calling start */ | ||||
| 
 | ||||
|   effp->global_info = &chain->global_info; | ||||
|   effp->in_signal = *in; | ||||
|   effp->out_signal = *out; | ||||
|   effp->in_encoding = chain->in_enc; | ||||
|   effp->out_encoding = chain->out_enc; | ||||
|   if (!(effp->handler.flags & SOX_EFF_CHAN)) | ||||
|     effp->out_signal.channels = in->channels; | ||||
|   if (!(effp->handler.flags & SOX_EFF_RATE)) | ||||
|     effp->out_signal.rate = in->rate; | ||||
|   if (!(effp->handler.flags & SOX_EFF_PREC)) | ||||
|     effp->out_signal.precision = (effp->handler.flags & SOX_EFF_MODIFY)? | ||||
|         in->precision : SOX_SAMPLE_PRECISION; | ||||
|   if (!(effp->handler.flags & SOX_EFF_GAIN)) | ||||
|     effp->out_signal.mult = in->mult; | ||||
| 
 | ||||
|   effp->flows = | ||||
|     (effp->handler.flags & SOX_EFF_MCHAN)? 1 : effp->in_signal.channels; | ||||
|   effp->clips = 0; | ||||
|   effp->imin = 0; | ||||
|   eff0 = *effp, eff0.priv = lsx_memdup(eff0.priv, eff0.handler.priv_size); | ||||
|   eff0.in_signal.mult = NULL; /* Only used in channel 0 */ | ||||
|   ret = start(effp); | ||||
|   if (ret == SOX_EFF_NULL) { | ||||
|     lsx_report("has no effect in this configuration"); | ||||
|     free(eff0.priv); | ||||
|     effp->handler.kill(effp); | ||||
|     free(effp->priv); | ||||
|     effp->priv = NULL; | ||||
|     return SOX_SUCCESS; | ||||
|   } | ||||
|   if (ret != SOX_SUCCESS) { | ||||
|     free(eff0.priv); | ||||
|     return SOX_EOF; | ||||
|   } | ||||
|   if (in->mult) | ||||
|     lsx_debug("mult=%g", *in->mult); | ||||
| 
 | ||||
|   if (!(effp->handler.flags & SOX_EFF_LENGTH)) { | ||||
|     effp->out_signal.length = in->length; | ||||
|     if (effp->out_signal.length != SOX_UNKNOWN_LEN) { | ||||
|       if (effp->handler.flags & SOX_EFF_CHAN) | ||||
|         effp->out_signal.length = | ||||
|           effp->out_signal.length / in->channels * effp->out_signal.channels; | ||||
|       if (effp->handler.flags & SOX_EFF_RATE) | ||||
|         effp->out_signal.length = | ||||
|           effp->out_signal.length / in->rate * effp->out_signal.rate + .5; | ||||
|     } | ||||
|   } | ||||
| 
 | ||||
|   *in = effp->out_signal; | ||||
| 
 | ||||
|   if (chain->length == chain->table_size) { | ||||
|     chain->table_size += EFF_TABLE_STEP; | ||||
|     lsx_debug_more("sox_add_effect: extending effects table, " | ||||
|       "new size = %" PRIuPTR, chain->table_size); | ||||
|     lsx_revalloc(chain->effects, chain->table_size); | ||||
|   } | ||||
| 
 | ||||
|   chain->effects[chain->length] = | ||||
|     lsx_calloc(effp->flows, sizeof(chain->effects[chain->length][0])); | ||||
|   chain->effects[chain->length][0] = *effp; | ||||
| 
 | ||||
|   for (f = 1; f < effp->flows; ++f) { | ||||
|     chain->effects[chain->length][f] = eff0; | ||||
|     chain->effects[chain->length][f].flow = f; | ||||
|     chain->effects[chain->length][f].priv = lsx_memdup(eff0.priv, eff0.handler.priv_size); | ||||
|     if (start(&chain->effects[chain->length][f]) != SOX_SUCCESS) { | ||||
|       free(eff0.priv); | ||||
|       return SOX_EOF; | ||||
|     } | ||||
|   } | ||||
| 
 | ||||
|   ++chain->length; | ||||
|   free(eff0.priv); | ||||
|   return SOX_SUCCESS; | ||||
| } | ||||
| 
 | ||||
| /* An effect's output buffer (effp->obuf) generally has this layout:
 | ||||
|  *   |. . . A1A2A3B1B2B3C1C2C3. . . . . . . . . . . . . . . . . . | | ||||
|  *    ^0    ^obeg             ^oend                               ^bufsiz | ||||
|  * (where A1 is the first sample of channel 1, A2 the first sample of | ||||
|  * channel 2, etc.), i.e. the channels are interleaved. | ||||
|  * However, while sox_flow_effects() is running, output buffers are | ||||
|  * adapted to how the following effect expects its input, to avoid | ||||
|  * back-and-forth conversions.  If the following effect operates on | ||||
|  * each of several channels separately (flows > 1), the layout is | ||||
|  * changed to this uninterleaved form: | ||||
|  *   |. A1B1C1. . . . . . . A2B2C2. . . . . . . A3B3C3. . . . . . | | ||||
|  *    ^0    ^obeg             ^oend                               ^bufsiz | ||||
|  *    <--- channel 1 ----><--- channel 2 ----><--- channel 3 ----> | ||||
|  * The buffer is logically subdivided into channel buffers of size | ||||
|  * bufsiz/flows each, starting at offsets 0, bufsiz/flows, | ||||
|  * 2*(bufsiz/flows) etc.  Within the channel buffers, the data starts | ||||
|  * at position obeg/flows and ends before oend/flows.  In case bufsiz | ||||
|  * is not evenly divisible by flows, there will be an unused area at | ||||
|  * the very end of the output buffer. | ||||
|  * The interleave() and deinterleave() functions convert between these | ||||
|  * two representations. | ||||
|  */ | ||||
| static void interleave(size_t flows, size_t length, sox_sample_t *from, | ||||
|     size_t bufsiz, size_t offset, sox_sample_t *to); | ||||
| static void deinterleave(size_t flows, size_t length, sox_sample_t *from, | ||||
|     sox_sample_t *to, size_t bufsiz, size_t offset); | ||||
| 
 | ||||
| static int flow_effect(sox_effects_chain_t * chain, size_t n) | ||||
| { | ||||
|   sox_effect_t *effp1 = chain->effects[n - 1]; | ||||
|   sox_effect_t *effp = chain->effects[n]; | ||||
|   int effstatus = SOX_SUCCESS; | ||||
|   size_t f = 0; | ||||
|   size_t idone = effp1->oend - effp1->obeg; | ||||
|   size_t obeg = sox_globals.bufsiz - effp->oend; | ||||
|   sox_bool il_change = (effp->flows == 1) != | ||||
|       (chain->length == n + 1 || chain->effects[n+1]->flows == 1); | ||||
| #if DEBUG_EFFECTS_CHAIN | ||||
|   size_t pre_idone = idone; | ||||
|   size_t pre_odone = obeg; | ||||
| #endif | ||||
| 
 | ||||
|   if (effp->flows == 1) {     /* Run effect on all channels at once */ | ||||
|     idone -= idone % effp->in_signal.channels; | ||||
|     effstatus = effp->handler.flow(effp, effp1->obuf + effp1->obeg, | ||||
|                     il_change ? chain->il_buf : effp->obuf + effp->oend, | ||||
|                     &idone, &obeg); | ||||
|     if (obeg % effp->out_signal.channels != 0) { | ||||
|       lsx_fail("multi-channel effect flowed asymmetrically!"); | ||||
|       effstatus = SOX_EOF; | ||||
|     } | ||||
|     if (il_change) | ||||
|       deinterleave(chain->effects[n+1]->flows, obeg, chain->il_buf, | ||||
|           effp->obuf, sox_globals.bufsiz, effp->oend); | ||||
|   } else {               /* Run effect on each channel individually */ | ||||
|     sox_sample_t *obuf = il_change ? chain->il_buf : effp->obuf; | ||||
|     size_t flow_offs = sox_globals.bufsiz/effp->flows; | ||||
|     size_t idone_min = SOX_SIZE_MAX, idone_max = 0; | ||||
|     size_t odone_min = SOX_SIZE_MAX, odone_max = 0; | ||||
| 
 | ||||
| #ifdef HAVE_OPENMP_3_1 | ||||
|     #pragma omp parallel for \ | ||||
|         if(sox_globals.use_threads) \
 | ||||
|         schedule(static) default(none) \
 | ||||
|         shared(effp,effp1,idone,obeg,obuf,flow_offs,chain,n,effstatus) \
 | ||||
|         reduction(min:idone_min,odone_min) reduction(max:idone_max,odone_max) | ||||
| #elif defined HAVE_OPENMP | ||||
|     #pragma omp parallel for \ | ||||
|         if(sox_globals.use_threads) \
 | ||||
|         schedule(static) default(none) \
 | ||||
|         shared(effp,effp1,idone,obeg,obuf,flow_offs,chain,n,effstatus) \
 | ||||
|         firstprivate(idone_min,odone_min,idone_max,odone_max) \
 | ||||
|         lastprivate(idone_min,odone_min,idone_max,odone_max) | ||||
| #endif | ||||
|     for (f = 0; f < effp->flows; ++f) { | ||||
|       size_t idonec = idone / effp->flows; | ||||
|       size_t odonec = obeg / effp->flows; | ||||
|       int eff_status_c = effp->handler.flow(&chain->effects[n][f], | ||||
|           effp1->obuf + f*flow_offs + effp1->obeg/effp->flows, | ||||
|           obuf + f*flow_offs + effp->oend/effp->flows, | ||||
|           &idonec, &odonec); | ||||
|       idone_min = min(idonec, idone_min); idone_max = max(idonec, idone_max); | ||||
|       odone_min = min(odonec, odone_min); odone_max = max(odonec, odone_max); | ||||
| 
 | ||||
|       if (eff_status_c != SOX_SUCCESS) | ||||
|         effstatus = SOX_EOF; | ||||
|     } | ||||
| 
 | ||||
|     if (idone_min != idone_max || odone_min != odone_max) { | ||||
|       lsx_fail("flowed asymmetrically!"); | ||||
|       effstatus = SOX_EOF; | ||||
|     } | ||||
|     idone = effp->flows * idone_max; | ||||
|     obeg = effp->flows * odone_max; | ||||
| 
 | ||||
|     if (il_change) | ||||
|       interleave(effp->flows, obeg, chain->il_buf, sox_globals.bufsiz, | ||||
|           effp->oend, effp->obuf + effp->oend); | ||||
|   } | ||||
|   effp1->obeg += idone; | ||||
|   if (effp1->obeg == effp1->oend) | ||||
|     effp1->obeg = effp1->oend = 0; | ||||
|   else if (effp1->oend - effp1->obeg < effp->imin) { /* Need to refill? */ | ||||
|     size_t flow_offs = sox_globals.bufsiz/effp->flows; | ||||
|     for (f = 0; f < effp->flows; ++f) | ||||
|       memcpy(effp1->obuf + f * flow_offs, | ||||
|           effp1->obuf + f * flow_offs + effp1->obeg/effp->flows, | ||||
|           (effp1->oend - effp1->obeg)/effp->flows * sizeof(*effp1->obuf)); | ||||
|     effp1->oend -= effp1->obeg; | ||||
|     effp1->obeg = 0; | ||||
|   } | ||||
| 
 | ||||
|   effp->oend += obeg; | ||||
| 
 | ||||
| #if DEBUG_EFFECTS_CHAIN | ||||
|   lsx_report("\t" "flow:  %2" PRIuPTR " (%1" PRIuPTR ")  " | ||||
|       "%5" PRIuPTR " %5" PRIuPTR " %5" PRIuPTR " %5" PRIuPTR "  " | ||||
|       "%5" PRIuPTR " [%" PRIuPTR "-%" PRIuPTR "]", | ||||
|       n, effp->flows, pre_idone, pre_odone, idone, obeg, | ||||
|       effp1->oend - effp1->obeg, effp1->obeg, effp1->oend); | ||||
| #endif | ||||
| 
 | ||||
|   return effstatus == SOX_SUCCESS? SOX_SUCCESS : SOX_EOF; | ||||
| } | ||||
| 
 | ||||
| /* The same as flow_effect but with no input */ | ||||
| static int drain_effect(sox_effects_chain_t * chain, size_t n) | ||||
| { | ||||
|   sox_effect_t *effp = chain->effects[n]; | ||||
|   int effstatus = SOX_SUCCESS; | ||||
|   size_t f = 0; | ||||
|   size_t obeg = sox_globals.bufsiz - effp->oend; | ||||
|   sox_bool il_change = (effp->flows == 1) != | ||||
|       (chain->length == n + 1 || chain->effects[n+1]->flows == 1); | ||||
| #if DEBUG_EFFECTS_CHAIN | ||||
|   size_t pre_odone = obeg; | ||||
| #endif | ||||
| 
 | ||||
|   if (effp->flows == 1) { /* Run effect on all channels at once */ | ||||
|     effstatus = effp->handler.drain(effp, | ||||
|                     il_change ? chain->il_buf : effp->obuf + effp->oend, | ||||
|                     &obeg); | ||||
|     if (obeg % effp->out_signal.channels != 0) { | ||||
|       lsx_fail("multi-channel effect drained asymmetrically!"); | ||||
|       effstatus = SOX_EOF; | ||||
|     } | ||||
|     if (il_change) | ||||
|       deinterleave(chain->effects[n+1]->flows, obeg, chain->il_buf, | ||||
|           effp->obuf, sox_globals.bufsiz, effp->oend); | ||||
|   } else {                       /* Run effect on each channel individually */ | ||||
|     sox_sample_t *obuf = il_change ? chain->il_buf : effp->obuf; | ||||
|     size_t flow_offs = sox_globals.bufsiz/effp->flows; | ||||
|     size_t odone_last = 0; /* Initialised to prevent warning */ | ||||
| 
 | ||||
|     for (f = 0; f < effp->flows; ++f) { | ||||
|       size_t odonec = obeg / effp->flows; | ||||
|       int eff_status_c = effp->handler.drain(&chain->effects[n][f], | ||||
|           obuf + f*flow_offs + effp->oend/effp->flows, | ||||
|           &odonec); | ||||
|       if (f && (odonec != odone_last)) { | ||||
|         lsx_fail("drained asymmetrically!"); | ||||
|         effstatus = SOX_EOF; | ||||
|       } | ||||
|       odone_last = odonec; | ||||
| 
 | ||||
|       if (eff_status_c != SOX_SUCCESS) | ||||
|         effstatus = SOX_EOF; | ||||
|     } | ||||
| 
 | ||||
|     obeg = effp->flows * odone_last; | ||||
| 
 | ||||
|     if (il_change) | ||||
|       interleave(effp->flows, obeg, chain->il_buf, sox_globals.bufsiz, | ||||
|           effp->oend, effp->obuf + effp->oend); | ||||
|   } | ||||
|   if (!obeg)   /* This is the only thing that drain has and flow hasn't */ | ||||
|     effstatus = SOX_EOF; | ||||
| 
 | ||||
|   effp->oend += obeg; | ||||
| 
 | ||||
| #if DEBUG_EFFECTS_CHAIN | ||||
|   lsx_report("\t" "drain: %2" PRIuPTR " (%1" PRIuPTR ")  " | ||||
|       "%5" PRIuPTR " %5" PRIuPTR " %5" PRIuPTR " %5" PRIuPTR, | ||||
|       n, effp->flows, (size_t)0, pre_odone, (size_t)0, obeg); | ||||
| #endif | ||||
| 
 | ||||
|   return effstatus == SOX_SUCCESS? SOX_SUCCESS : SOX_EOF; | ||||
| } | ||||
| 
 | ||||
| /* Flow data through the effects chain until an effect or callback gives EOF */ | ||||
| int sox_flow_effects(sox_effects_chain_t * chain, int (* callback)(sox_bool all_done, void * client_data), void * client_data) | ||||
| { | ||||
|   int flow_status = SOX_SUCCESS; | ||||
|   size_t e, source_e = 0;               /* effect indices */ | ||||
|   size_t max_flows = 0; | ||||
|   sox_bool draining = sox_true; | ||||
| 
 | ||||
|   for (e = 0; e < chain->length; ++e) { | ||||
|     sox_effect_t *effp = chain->effects[e]; | ||||
|     effp->obuf = | ||||
|         lsx_realloc(effp->obuf, sox_globals.bufsiz * sizeof(*effp->obuf)); | ||||
|       /* Memory will be freed by sox_delete_effect() later. */ | ||||
|       /* Possibly there was already a buffer, if this is a used effect;
 | ||||
|          it may still contain samples in that case. */ | ||||
|       if (effp->oend > sox_globals.bufsiz) { | ||||
|         lsx_warn("buffer size insufficient; buffered samples were dropped"); | ||||
|         /* can only happen if bufsize has been reduced since the last run */ | ||||
|         effp->obeg = effp->oend = 0; | ||||
|       } | ||||
|     max_flows = max(max_flows, effp->flows); | ||||
|   } | ||||
|   if (max_flows > 1) /* might need interleave buffer */ | ||||
|     chain->il_buf = lsx_malloc(sox_globals.bufsiz * sizeof(sox_sample_t)); | ||||
|   else | ||||
|     chain->il_buf = NULL; | ||||
| 
 | ||||
|   /* Go through the effects, and if there are samples in one of the
 | ||||
|      buffers, deinterleave it (if necessary).  */ | ||||
|   for (e = 0; e + 1 < chain->length; e++) { | ||||
|     sox_effect_t *effp = chain->effects[e]; | ||||
|     if (effp->oend > effp->obeg && chain->effects[e+1]->flows > 1) { | ||||
|       sox_sample_t *sw = chain->il_buf; chain->il_buf = effp->obuf; effp->obuf = sw; | ||||
|       deinterleave(chain->effects[e+1]->flows, effp->oend - effp->obeg, | ||||
|           chain->il_buf, effp->obuf, sox_globals.bufsiz, effp->obeg); | ||||
|     } | ||||
|   } | ||||
| 
 | ||||
|   e = chain->length - 1; | ||||
|   while (source_e < chain->length) { | ||||
| #define have_imin (e > 0 && e < chain->length && chain->effects[e - 1]->oend - chain->effects[e - 1]->obeg >= chain->effects[e]->imin) | ||||
|     size_t osize = chain->effects[e]->oend - chain->effects[e]->obeg; | ||||
|     if (e == source_e && (draining || !have_imin)) { | ||||
|       if (drain_effect(chain, e) == SOX_EOF) { | ||||
|         ++source_e; | ||||
|         draining = sox_false; | ||||
|       } | ||||
|     } else if (have_imin && flow_effect(chain, e) == SOX_EOF) { | ||||
|       flow_status = SOX_EOF; | ||||
|       if (e == chain->length - 1) | ||||
|         break; | ||||
|       source_e = e; | ||||
|       draining = sox_true; | ||||
|     } | ||||
|     if (e < chain->length && chain->effects[e]->oend - chain->effects[e]->obeg > osize) /* False for output */ | ||||
|       ++e; | ||||
|     else if (e == source_e) | ||||
|       draining = sox_true; | ||||
|     else if (e < source_e) | ||||
|       e = source_e; | ||||
|     else | ||||
|       --e; | ||||
| 
 | ||||
|     if (callback && callback(source_e == chain->length, client_data) != SOX_SUCCESS) { | ||||
|       flow_status = SOX_EOF; /* Client has requested to stop the flow. */ | ||||
|       break; | ||||
|     } | ||||
|   } | ||||
| 
 | ||||
|   /* If an effect's output buffer still has samples, and if it is
 | ||||
|      uninterleaved, then re-interleave it. Necessary since it might | ||||
|      be reused, and at that time possibly followed by an MCHAN effect. */ | ||||
|   for (e = 0; e + 1 < chain->length; e++) { | ||||
|     sox_effect_t *effp = chain->effects[e]; | ||||
|     if (effp->oend > effp->obeg && chain->effects[e+1]->flows > 1) { | ||||
|       sox_sample_t *sw = chain->il_buf; chain->il_buf = effp->obuf; effp->obuf = sw; | ||||
|       interleave(chain->effects[e+1]->flows, effp->oend - effp->obeg, | ||||
|           chain->il_buf, sox_globals.bufsiz, effp->obeg, effp->obuf); | ||||
|     } | ||||
|   } | ||||
| 
 | ||||
|   free(chain->il_buf); | ||||
|   return flow_status; | ||||
| } | ||||
| 
 | ||||
| sox_uint64_t sox_effects_clips(sox_effects_chain_t * chain) | ||||
| { | ||||
|   size_t i, f; | ||||
|   uint64_t clips = 0; | ||||
|   for (i = 1; i < chain->length - 1; ++i) | ||||
|     for (f = 0; f < chain->effects[i][0].flows; ++f) | ||||
|       clips += chain->effects[i][f].clips; | ||||
|   return clips; | ||||
| } | ||||
| 
 | ||||
| sox_uint64_t sox_stop_effect(sox_effect_t *effp) | ||||
| { | ||||
|   size_t f; | ||||
|   uint64_t clips = 0; | ||||
| 
 | ||||
|   for (f = 0; f < effp->flows; ++f) { | ||||
|     effp[f].handler.stop(&effp[f]); | ||||
|     clips += effp[f].clips; | ||||
|   } | ||||
|   return clips; | ||||
| } | ||||
| 
 | ||||
| void sox_push_effect_last(sox_effects_chain_t *chain, sox_effect_t *effp) | ||||
| { | ||||
|   if (chain->length == chain->table_size) { | ||||
|     chain->table_size += EFF_TABLE_STEP; | ||||
|     lsx_debug_more("sox_push_effect_last: extending effects table, " | ||||
|         "new size = %" PRIuPTR, chain->table_size); | ||||
|     lsx_revalloc(chain->effects, chain->table_size); | ||||
|   } | ||||
| 
 | ||||
|   chain->effects[chain->length++] = effp; | ||||
| } /* sox_push_effect_last */ | ||||
| 
 | ||||
| sox_effect_t *sox_pop_effect_last(sox_effects_chain_t *chain) | ||||
| { | ||||
|   if (chain->length > 0) | ||||
|   { | ||||
|     sox_effect_t *effp; | ||||
|     chain->length--; | ||||
|     effp = chain->effects[chain->length]; | ||||
|     chain->effects[chain->length] = NULL; | ||||
|     return effp; | ||||
|   } | ||||
|   else | ||||
|     return NULL; | ||||
| } /* sox_pop_effect_last */ | ||||
| 
 | ||||
| /* Free resources related to effect.
 | ||||
|  * Note: This currently closes down the effect which might | ||||
|  * not be obvious from name. | ||||
|  */ | ||||
| void sox_delete_effect(sox_effect_t *effp) | ||||
| { | ||||
|   uint64_t clips; | ||||
|   size_t f; | ||||
| 
 | ||||
|   if ((clips = sox_stop_effect(effp)) != 0) | ||||
|     lsx_warn("%s clipped %" PRIu64 " samples; decrease volume?", | ||||
|         effp->handler.name, clips); | ||||
|   if (effp->obeg != effp->oend) | ||||
|     lsx_debug("output buffer still held %" PRIuPTR " samples; dropped.", | ||||
|         (effp->oend - effp->obeg)/effp->out_signal.channels); | ||||
|       /* May or may not indicate a problem; it is normal if the user aborted
 | ||||
|          processing, or if an effect like "trim" stopped early. */ | ||||
|   effp->handler.kill(effp); /* N.B. only one kill; not one per flow */ | ||||
|   for (f = 0; f < effp->flows; ++f) | ||||
|     free(effp[f].priv); | ||||
|   free(effp->obuf); | ||||
|   free(effp); | ||||
| } | ||||
| 
 | ||||
| void sox_delete_effect_last(sox_effects_chain_t *chain) | ||||
| { | ||||
|   if (chain->length > 0) | ||||
|   { | ||||
|     chain->length--; | ||||
|     sox_delete_effect(chain->effects[chain->length]); | ||||
|     chain->effects[chain->length] = NULL; | ||||
|   } | ||||
| } /* sox_delete_effect_last */ | ||||
| 
 | ||||
| /* Remove all effects from the chain.
 | ||||
|  * Note: This currently closes down the effect which might | ||||
|  * not be obvious from name. | ||||
|  */ | ||||
| void sox_delete_effects(sox_effects_chain_t * chain) | ||||
| { | ||||
|   size_t e; | ||||
| 
 | ||||
|   for (e = 0; e < chain->length; ++e) { | ||||
|     sox_delete_effect(chain->effects[e]); | ||||
|     chain->effects[e] = NULL; | ||||
|   } | ||||
|   chain->length = 0; | ||||
| } | ||||
| 
 | ||||
| /*----------------------------- Effects library ------------------------------*/ | ||||
| 
 | ||||
| static sox_effect_fn_t s_sox_effect_fns[] = { | ||||
| #define EFFECT(f) lsx_##f##_effect_fn, | ||||
| #include "effects.h" | ||||
| #undef EFFECT | ||||
|   NULL | ||||
| }; | ||||
| 
 | ||||
| const sox_effect_fn_t* | ||||
| sox_get_effect_fns(void) | ||||
| { | ||||
|     return s_sox_effect_fns; | ||||
| } | ||||
| 
 | ||||
| /* Find a named effect in the effects library */ | ||||
| sox_effect_handler_t const * sox_find_effect(char const * name) | ||||
| { | ||||
|   int e; | ||||
|   sox_effect_fn_t const * fns = sox_get_effect_fns(); | ||||
|   for (e = 0; fns[e]; ++e) { | ||||
|     const sox_effect_handler_t *eh = fns[e] (); | ||||
|     if (eh && eh->name && strcasecmp(eh->name, name) == 0) | ||||
|       return eh;                 /* Found it. */ | ||||
|   } | ||||
|   return NULL; | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| /*----------------------------- Helper functions -----------------------------*/ | ||||
| 
 | ||||
| /* interleave() parameters:
 | ||||
|  *   flows: number of samples per wide sample | ||||
|  *   length: number of samples to copy | ||||
|  *     [pertaining to the (non-interleaved) source buffer:] | ||||
|  *   from: start address | ||||
|  *   bufsiz: total size | ||||
|  *   offset: position at which to start reading | ||||
|  *     [pertaining to the (interleaved) destination buffer:] | ||||
|  *   to: start address | ||||
|  */ | ||||
| static void interleave(size_t flows, size_t length, sox_sample_t *from, | ||||
|     size_t bufsiz, size_t offset, sox_sample_t *to) | ||||
| { | ||||
|   size_t i; | ||||
|   const size_t wide_samples = length/flows; | ||||
|   const size_t flow_offs = bufsiz/flows; | ||||
|   from += offset/flows; | ||||
|   for (i = 0; i < wide_samples; i++) { | ||||
|     sox_sample_t *inner_from = from + i; | ||||
|     sox_sample_t *inner_to = to + i * flows; | ||||
|     size_t f; | ||||
|     for (f = 0; f < flows; f++) { | ||||
|       *inner_to++ = *inner_from; | ||||
|       inner_from += flow_offs; | ||||
|     } | ||||
|   } | ||||
| } | ||||
| 
 | ||||
| /* deinterleave() parameters:
 | ||||
|  *   flows: number of samples per wide sample | ||||
|  *   length: number of samples to copy | ||||
|  *     [pertaining to the (interleaved) source buffer:] | ||||
|  *   from: start address | ||||
|  *     [pertaining to the (non-interleaved) destination buffer:] | ||||
|  *   to: start address | ||||
|  *   bufsiz: total size | ||||
|  *   offset: position at which to start writing | ||||
|  */ | ||||
| static void deinterleave(size_t flows, size_t length, sox_sample_t *from, | ||||
|     sox_sample_t *to, size_t bufsiz, size_t offset) | ||||
| { | ||||
|   const size_t wide_samples = length/flows; | ||||
|   const size_t flow_offs = bufsiz/flows; | ||||
|   size_t f; | ||||
|   to += offset/flows; | ||||
|   for (f = 0; f < flows; f++) { | ||||
|     sox_sample_t *inner_to = to + f*flow_offs; | ||||
|     sox_sample_t *inner_from = from + f; | ||||
|     size_t i = wide_samples; | ||||
|     while (i--) { | ||||
|       *inner_to++ = *inner_from; | ||||
|       inner_from += flows; | ||||
|     } | ||||
|   } | ||||
| } | ||||
| @ -1,38 +0,0 @@ | ||||
| /* This library is free software; you can redistribute it and/or modify it
 | ||||
|  * under the terms of the GNU Lesser General Public License as published by | ||||
|  * the Free Software Foundation; either version 2.1 of the License, or (at | ||||
|  * your option) any later version. | ||||
|  * | ||||
|  * This library is distributed in the hope that it will be useful, but | ||||
|  * WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser | ||||
|  * General Public License for more details. | ||||
|  * | ||||
|  * You should have received a copy of the GNU Lesser General Public License | ||||
|  * along with this library; if not, write to the Free Software Foundation, | ||||
|  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA | ||||
|  */ | ||||
| 
 | ||||
| /* FIXME: generate this list automatically */ | ||||
| 
 | ||||
|   EFFECT(delay) | ||||
|   EFFECT(downsample) | ||||
|   EFFECT(echo) | ||||
|   EFFECT(echos) | ||||
|   EFFECT(input) | ||||
| #ifdef HAVE_LADSPA_H | ||||
|   EFFECT(ladspa) | ||||
| #endif | ||||
|   EFFECT(output) | ||||
|   EFFECT(reverb) | ||||
| #ifdef HAVE_PNG | ||||
|   EFFECT(spectrogram) | ||||
| #endif | ||||
|   EFFECT(speed) | ||||
| #ifdef HAVE_SPEEXDSP | ||||
|   EFFECT(speexdsp) | ||||
| #endif | ||||
|   EFFECT(tempo) | ||||
|   EFFECT(upsample) | ||||
|   EFFECT(vad) | ||||
|   EFFECT(vol) | ||||
| @ -1,483 +0,0 @@ | ||||
| /* Implements a libSoX internal interface for implementing effects.
 | ||||
|  * All public functions & data are prefixed with lsx_ . | ||||
|  * | ||||
|  * Copyright (c) 2005-2012 Chris Bagwell and SoX contributors | ||||
|  * | ||||
|  * This library is free software; you can redistribute it and/or modify it | ||||
|  * under the terms of the GNU Lesser General Public License as published by | ||||
|  * the Free Software Foundation; either version 2.1 of the License, or (at | ||||
|  * your option) any later version. | ||||
|  * | ||||
|  * This library is distributed in the hope that it will be useful, but | ||||
|  * WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser | ||||
|  * General Public License for more details. | ||||
|  * | ||||
|  * You should have received a copy of the GNU Lesser General Public License | ||||
|  * along with this library; if not, write to the Free Software Foundation, | ||||
|  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA | ||||
|  */ | ||||
| 
 | ||||
| #define LSX_EFF_ALIAS | ||||
| #include "sox_i.h" | ||||
| #include <string.h> | ||||
| #include <ctype.h> | ||||
| 
 | ||||
| int lsx_usage(sox_effect_t * effp) | ||||
| { | ||||
|   if (effp->handler.usage) | ||||
|     lsx_fail("usage: %s", effp->handler.usage); | ||||
|   else | ||||
|     lsx_fail("this effect takes no parameters"); | ||||
|   return SOX_EOF; | ||||
| } | ||||
| 
 | ||||
| char * lsx_usage_lines(char * * usage, char const * const * lines, size_t n) | ||||
| { | ||||
|   if (!*usage) { | ||||
|     size_t i, len; | ||||
|     for (len = i = 0; i < n; len += strlen(lines[i++]) + 1); | ||||
|     *usage = lsx_malloc(len); /* FIXME: this memory will never be freed */ | ||||
|     strcpy(*usage, lines[0]); | ||||
|     for (i = 1; i < n; ++i) { | ||||
|       strcat(*usage, "\n"); | ||||
|       strcat(*usage, lines[i]); | ||||
|     } | ||||
|   } | ||||
|   return *usage; | ||||
| } | ||||
| 
 | ||||
| static lsx_enum_item const s_lsx_wave_enum[] = { | ||||
|   LSX_ENUM_ITEM(SOX_WAVE_,SINE) | ||||
|   LSX_ENUM_ITEM(SOX_WAVE_,TRIANGLE) | ||||
|   {0, 0}}; | ||||
| 
 | ||||
| lsx_enum_item const * lsx_get_wave_enum(void) | ||||
| { | ||||
|   return s_lsx_wave_enum; | ||||
| } | ||||
| 
 | ||||
| void lsx_generate_wave_table( | ||||
|     lsx_wave_t wave_type, | ||||
|     sox_data_t data_type, | ||||
|     void *table, | ||||
|     size_t table_size, | ||||
|     double min, | ||||
|     double max, | ||||
|     double phase) | ||||
| { | ||||
|   uint32_t t; | ||||
|   uint32_t phase_offset = phase / M_PI / 2 * table_size + 0.5; | ||||
| 
 | ||||
|   for (t = 0; t < table_size; t++) | ||||
|   { | ||||
|     uint32_t point = (t + phase_offset) % table_size; | ||||
|     double d; | ||||
|     switch (wave_type) | ||||
|     { | ||||
|       case SOX_WAVE_SINE: | ||||
|       d = (sin((double)point / table_size * 2 * M_PI) + 1) / 2; | ||||
|       break; | ||||
| 
 | ||||
|       case SOX_WAVE_TRIANGLE: | ||||
|       d = (double)point * 2 / table_size; | ||||
|       switch (4 * point / table_size) | ||||
|       { | ||||
|         case 0:         d = d + 0.5; break; | ||||
|         case 1: case 2: d = 1.5 - d; break; | ||||
|         case 3:         d = d - 1.5; break; | ||||
|       } | ||||
|       break; | ||||
| 
 | ||||
|       default: /* Oops! FIXME */ | ||||
|         d = 0.0; /* Make sure we have a value */ | ||||
|       break; | ||||
|     } | ||||
|     d  = d * (max - min) + min; | ||||
|     switch (data_type) | ||||
|     { | ||||
|       case SOX_FLOAT: | ||||
|         { | ||||
|           float *fp = (float *)table; | ||||
|           *fp++ = (float)d; | ||||
|           table = fp; | ||||
|           continue; | ||||
|         } | ||||
|       case SOX_DOUBLE: | ||||
|         { | ||||
|           double *dp = (double *)table; | ||||
|           *dp++ = d; | ||||
|           table = dp; | ||||
|           continue; | ||||
|         } | ||||
|       default: break; | ||||
|     } | ||||
|     d += d < 0? -0.5 : +0.5; | ||||
|     switch (data_type) | ||||
|     { | ||||
|       case SOX_SHORT: | ||||
|         { | ||||
|           short *sp = table; | ||||
|           *sp++ = (short)d; | ||||
|           table = sp; | ||||
|           continue; | ||||
|         } | ||||
|       case SOX_INT: | ||||
|         { | ||||
|           int *ip = table; | ||||
|           *ip++ = (int)d; | ||||
|           table = ip; | ||||
|           continue; | ||||
|         } | ||||
|       default: break; | ||||
|     } | ||||
|   } | ||||
| } | ||||
| 
 | ||||
| /*
 | ||||
|  * lsx_parsesamples | ||||
|  * | ||||
|  * Parse a string for # of samples.  The input consists of one or more | ||||
|  * parts, with '+' or '-' between them indicating if the sample count | ||||
|  * should be added to or subtracted from the previous value. | ||||
|  * If a part ends with a 's' then it is interpreted as a | ||||
|  * user-calculated # of samples. | ||||
|  * If a part contains ':' or '.' but no 'e' or if it ends with a 't' | ||||
|  * then it is treated as an amount of time.  This is converted into | ||||
|  * seconds and fraction of seconds, then the sample rate is used to | ||||
|  * calculate # of samples. | ||||
|  * Parameter def specifies which interpretation should be the default | ||||
|  * for a bare number like "123".  It can either be 't' or 's'. | ||||
|  * Returns NULL on error, pointer to next char to parse otherwise. | ||||
|  */ | ||||
| static char const * parsesamples(sox_rate_t rate, const char *str0, uint64_t *samples, int def, int combine); | ||||
| 
 | ||||
| char const * lsx_parsesamples(sox_rate_t rate, const char *str0, uint64_t *samples, int def) | ||||
| { | ||||
|   *samples = 0; | ||||
|   return parsesamples(rate, str0, samples, def, '+'); | ||||
| } | ||||
| 
 | ||||
| static char const * parsesamples(sox_rate_t rate, const char *str0, uint64_t *samples, int def, int combine) | ||||
| { | ||||
|   char * str = (char *)str0; | ||||
| 
 | ||||
|   do { | ||||
|     uint64_t samples_part; | ||||
|     sox_bool found_samples = sox_false, found_time = sox_false; | ||||
|     char const * end; | ||||
|     char const * pos; | ||||
|     sox_bool found_colon, found_dot, found_e; | ||||
| 
 | ||||
|     for (;*str == ' '; ++str); | ||||
|     for (end = str; *end && strchr("0123456789:.ets", *end); ++end); | ||||
|     if (end == str) | ||||
|       return NULL; /* error: empty input */ | ||||
| 
 | ||||
|     pos = strchr(str, ':'); | ||||
|     found_colon = pos && pos < end; | ||||
| 
 | ||||
|     pos = strchr(str, '.'); | ||||
|     found_dot = pos && pos < end; | ||||
| 
 | ||||
|     pos = strchr(str, 'e'); | ||||
|     found_e = pos && pos < end; | ||||
| 
 | ||||
|     if (found_colon || (found_dot && !found_e) || *(end-1) == 't') | ||||
|       found_time = sox_true; | ||||
|     else if (*(end-1) == 's') | ||||
|       found_samples = sox_true; | ||||
| 
 | ||||
|     if (found_time || (def == 't' && !found_samples)) { | ||||
|       int i; | ||||
|       if (found_e) | ||||
|         return NULL; /* error: e notation in time */ | ||||
| 
 | ||||
|       for (samples_part = 0, i = 0; *str != '.' && i < 3; ++i) { | ||||
|         char * last_str = str; | ||||
|         long part = strtol(str, &str, 10); | ||||
|         if (!i && str == last_str) | ||||
|           return NULL; /* error: empty first component */ | ||||
|         samples_part += rate * part; | ||||
|         if (i < 2) { | ||||
|           if (*str != ':') | ||||
|             break; | ||||
|           ++str; | ||||
|           samples_part *= 60; | ||||
|         } | ||||
|       } | ||||
|       if (*str == '.') { | ||||
|         char * last_str = str; | ||||
|         double part = strtod(str, &str); | ||||
|         if (str == last_str) | ||||
|           return NULL; /* error: empty fractional part */ | ||||
|         samples_part += rate * part + .5; | ||||
|       } | ||||
|       if (*str == 't') | ||||
|         str++; | ||||
|     } else { | ||||
|       char * last_str = str; | ||||
|       double part = strtod(str, &str); | ||||
|       if (str == last_str) | ||||
|         return NULL; /* error: no sample count */ | ||||
|       samples_part = part + .5; | ||||
|       if (*str == 's') | ||||
|         str++; | ||||
|     } | ||||
|     if (str != end) | ||||
|       return NULL; /* error: trailing characters */ | ||||
| 
 | ||||
|     switch (combine) { | ||||
|       case '+': *samples += samples_part; break; | ||||
|       case '-': *samples = samples_part <= *samples ? | ||||
|                            *samples - samples_part : 0; | ||||
|         break; | ||||
|     } | ||||
|     combine = '\0'; | ||||
|     if (*str && strchr("+-", *str)) | ||||
|       combine = *str++; | ||||
|   } while (combine); | ||||
|   return str; | ||||
| } | ||||
| 
 | ||||
| #if 0 | ||||
| 
 | ||||
| #include <assert.h> | ||||
| 
 | ||||
| #define TEST(st, samp, len) \ | ||||
|   str = st; \
 | ||||
|   next = lsx_parsesamples(10000, str, &samples, 't'); \
 | ||||
|   assert(samples == samp && next == str + len); | ||||
| 
 | ||||
| int main(int argc, char * * argv) | ||||
| { | ||||
|   char const * str, * next; | ||||
|   uint64_t samples; | ||||
| 
 | ||||
|   TEST("0"  , 0, 1) | ||||
|   TEST("1" , 10000, 1) | ||||
| 
 | ||||
|   TEST("0s" , 0, 2) | ||||
|   TEST("0s,", 0, 2) | ||||
|   TEST("0s/", 0, 2) | ||||
|   TEST("0s@", 0, 2) | ||||
| 
 | ||||
|   TEST("0t" , 0, 2) | ||||
|   TEST("0t,", 0, 2) | ||||
|   TEST("0t/", 0, 2) | ||||
|   TEST("0t@", 0, 2) | ||||
| 
 | ||||
|   TEST("1s" , 1, 2) | ||||
|   TEST("1s,", 1, 2) | ||||
|   TEST("1s/", 1, 2) | ||||
|   TEST("1s@", 1, 2) | ||||
|   TEST(" 01s" , 1, 4) | ||||
|   TEST("1e6s" , 1000000, 4) | ||||
| 
 | ||||
|   TEST("1t" , 10000, 2) | ||||
|   TEST("1t,", 10000, 2) | ||||
|   TEST("1t/", 10000, 2) | ||||
|   TEST("1t@", 10000, 2) | ||||
|   TEST("1.1t" , 11000, 4) | ||||
|   TEST("1.1t,", 11000, 4) | ||||
|   TEST("1.1t/", 11000, 4) | ||||
|   TEST("1.1t@", 11000, 4) | ||||
|   assert(!lsx_parsesamples(10000, "1e6t", &samples, 't')); | ||||
| 
 | ||||
|   TEST(".0", 0, 2) | ||||
|   TEST("0.0", 0, 3) | ||||
|   TEST("0:0.0", 0, 5) | ||||
|   TEST("0:0:0.0", 0, 7) | ||||
| 
 | ||||
|   TEST(".1", 1000, 2) | ||||
|   TEST(".10", 1000, 3) | ||||
|   TEST("0.1", 1000, 3) | ||||
|   TEST("1.1", 11000, 3) | ||||
|   TEST("1:1.1", 611000, 5) | ||||
|   TEST("1:1:1.1", 36611000, 7) | ||||
|   TEST("1:1", 610000, 3) | ||||
|   TEST("1:01", 610000, 4) | ||||
|   TEST("1:1:1", 36610000, 5) | ||||
|   TEST("1:", 600000, 2) | ||||
|   TEST("1::", 36000000, 3) | ||||
| 
 | ||||
|   TEST("0.444444", 4444, 8) | ||||
|   TEST("0.555555", 5556, 8) | ||||
| 
 | ||||
|   assert(!lsx_parsesamples(10000, "x", &samples, 't')); | ||||
| 
 | ||||
|   TEST("1:23+37", 1200000, 7) | ||||
|   TEST("12t+12s",  120012, 7) | ||||
|   TEST("1e6s-10",  900000, 7) | ||||
|   TEST("10-2:00",       0, 7) | ||||
|   TEST("123-45+12s+2:00-3e3s@foo", 1977012, 20) | ||||
| 
 | ||||
|   TEST("1\0" "2", 10000, 1) | ||||
| 
 | ||||
|   return 0; | ||||
| } | ||||
| #endif | ||||
| 
 | ||||
| /*
 | ||||
|  * lsx_parseposition | ||||
|  * | ||||
|  * Parse a string for an audio position.  Similar to lsx_parsesamples | ||||
|  * above, but an initial '=', '+' or '-' indicates that the specified time | ||||
|  * is relative to the start of audio, last used position or end of audio, | ||||
|  * respectively.  Parameter def states which of these is the default. | ||||
|  * Parameters latest and end are the positions to which '+' and '-' relate; | ||||
|  * end may be SOX_UNKNOWN_LEN, in which case "-0" is the only valid | ||||
|  * end-relative input and will result in a position of SOX_UNKNOWN_LEN. | ||||
|  * Other parameters and return value are the same as for lsx_parsesamples. | ||||
|  * | ||||
|  * A test parse that only checks for valid syntax can be done by | ||||
|  * specifying samples = NULL.  If this passes, a later reparse of the same | ||||
|  * input will only fail if it is relative to the end ("-"), not "-0", and | ||||
|  * the end position is unknown. | ||||
|  */ | ||||
| char const * lsx_parseposition(sox_rate_t rate, const char *str0, uint64_t *samples, uint64_t latest, uint64_t end, int def) | ||||
| { | ||||
|   char *str = (char *)str0; | ||||
|   char anchor, combine; | ||||
| 
 | ||||
|   if (!strchr("+-=", def)) | ||||
|     return NULL; /* error: invalid default anchor */ | ||||
|   anchor = def; | ||||
|   if (*str && strchr("+-=", *str)) | ||||
|     anchor = *str++; | ||||
| 
 | ||||
|   combine = '+'; | ||||
|   if (strchr("+-", anchor)) { | ||||
|     combine = anchor; | ||||
|     if (*str && strchr("+-", *str)) | ||||
|       combine = *str++; | ||||
|   } | ||||
| 
 | ||||
|   if (!samples) { | ||||
|     /* dummy parse, syntax checking only */ | ||||
|     uint64_t dummy = 0; | ||||
|     return parsesamples(0., str, &dummy, 't', '+'); | ||||
|   } | ||||
| 
 | ||||
|   switch (anchor) { | ||||
|     case '=': *samples = 0; break; | ||||
|     case '+': *samples = latest; break; | ||||
|     case '-': *samples = end; break; | ||||
|   } | ||||
| 
 | ||||
|   if (anchor == '-' && end == SOX_UNKNOWN_LEN) { | ||||
|     /* "-0" only valid input here */ | ||||
|     char const *l; | ||||
|     for (l = str; *l && strchr("0123456789:.ets+-", *l); ++l); | ||||
|     if (l == str+1 && *str == '0') { | ||||
|       /* *samples already set to SOX_UNKNOWN_LEN */ | ||||
|       return l; | ||||
|     } | ||||
|     return NULL; /* error: end-relative position, but end unknown */ | ||||
|   } | ||||
| 
 | ||||
|   return parsesamples(rate, str, samples, 't', combine); | ||||
| } | ||||
| 
 | ||||
| /* a note is given as an int,
 | ||||
|  * 0   => 440 Hz = A | ||||
|  * >0  => number of half notes 'up', | ||||
|  * <0  => number of half notes down, | ||||
|  * example 12 => A of next octave, 880Hz | ||||
|  * | ||||
|  * calculated by freq = 440Hz * 2**(note/12) | ||||
|  */ | ||||
| static double calc_note_freq(double note, int key) | ||||
| { | ||||
|   if (key != INT_MAX) {                         /* Just intonation. */ | ||||
|     static const int n[] = {16, 9, 6, 5, 4, 7}; /* Numerator. */ | ||||
|     static const int d[] = {15, 8, 5, 4, 3, 5}; /* Denominator. */ | ||||
|     static double j[13];                        /* Just semitones */ | ||||
|     int i, m = floor(note); | ||||
| 
 | ||||
|     if (!j[1]) for (i = 1; i <= 12; ++i) | ||||
|       j[i] = i <= 6? log((double)n[i - 1] / d[i - 1]) / log(2.) : 1 - j[12 - i]; | ||||
|     note -= m; | ||||
|     m -= key = m - ((INT_MAX / 2 - ((INT_MAX / 2) % 12) + m - key) % 12); | ||||
|     return 440 * pow(2., key / 12. + j[m] + (j[m + 1] - j[m]) * note); | ||||
|   } | ||||
|   return 440 * pow(2., note / 12); | ||||
| } | ||||
| 
 | ||||
| int lsx_parse_note(char const * text, char * * end_ptr) | ||||
| { | ||||
|   int result = INT_MAX; | ||||
| 
 | ||||
|   if (*text >= 'A' && *text <= 'G') { | ||||
|     result = (int)(5/3. * (*text++ - 'A') + 9.5) % 12 - 9; | ||||
|     if (*text == 'b') {--result; ++text;} | ||||
|     else if (*text == '#') {++result; ++text;} | ||||
|     if (isdigit((unsigned char)*text)) | ||||
|       result += 12 * (*text++ - '4'); 
 | ||||
|   } | ||||
|   *end_ptr = (char *)text; | ||||
|   return result; | ||||
| } | ||||
| 
 | ||||
| /* Read string 'text' and convert to frequency.
 | ||||
|  * 'text' can be a positive number which is the frequency in Hz. | ||||
|  * If 'text' starts with a '%' and a following number the corresponding | ||||
|  * note is calculated. | ||||
|  * Return -1 on error. | ||||
|  */ | ||||
| double lsx_parse_frequency_k(char const * text, char * * end_ptr, int key) | ||||
| { | ||||
|   double result; | ||||
| 
 | ||||
|   if (*text == '%') { | ||||
|     result = strtod(text + 1, end_ptr); | ||||
|     if (*end_ptr == text + 1) | ||||
|       return -1; | ||||
|     return calc_note_freq(result, key); | ||||
|   } | ||||
|   if (*text >= 'A' && *text <= 'G') { | ||||
|     int result2 = lsx_parse_note(text, end_ptr); | ||||
|     return result2 == INT_MAX? - 1 : calc_note_freq((double)result2, key); | ||||
|   } | ||||
|   result = strtod(text, end_ptr); | ||||
|   if (end_ptr) { | ||||
|     if (*end_ptr == text) | ||||
|       return -1; | ||||
|     if (**end_ptr == 'k') { | ||||
|       result *= 1000; | ||||
|       ++*end_ptr; | ||||
|     } | ||||
|   } | ||||
|   return result < 0 ? -1 : result; | ||||
| } | ||||
| 
 | ||||
| FILE * lsx_open_input_file(sox_effect_t * effp, char const * filename, sox_bool text_mode) | ||||
| { | ||||
|   FILE * file; | ||||
| 
 | ||||
|   if (!filename || !strcmp(filename, "-")) { | ||||
|     if (effp->global_info->global_info->stdin_in_use_by) { | ||||
|       lsx_fail("stdin already in use by `%s'", effp->global_info->global_info->stdin_in_use_by); | ||||
|       return NULL; | ||||
|     } | ||||
|     effp->global_info->global_info->stdin_in_use_by = effp->handler.name; | ||||
|     file = stdin; | ||||
|   } | ||||
|   else if (!(file = fopen(filename, text_mode ? "r" : "rb"))) { | ||||
|     lsx_fail("couldn't open file %s: %s", filename, strerror(errno)); | ||||
|     return NULL; | ||||
|   } | ||||
|   return file; | ||||
| } | ||||
| 
 | ||||
| int lsx_effects_init(void) | ||||
| { | ||||
|   init_fft_cache(); | ||||
|   return SOX_SUCCESS; | ||||
| } | ||||
| 
 | ||||
| int lsx_effects_quit(void) | ||||
| { | ||||
|   clear_fft_cache(); | ||||
|   return SOX_SUCCESS; | ||||
| } | ||||
| @ -1,645 +0,0 @@ | ||||
| /* libSoX internal DSP functions.
 | ||||
|  * All public functions & data are prefixed with lsx_ . | ||||
|  * | ||||
|  * Copyright (c) 2008,2012 robs@users.sourceforge.net | ||||
|  * | ||||
|  * This library is free software; you can redistribute it and/or modify it | ||||
|  * under the terms of the GNU Lesser General Public License as published by | ||||
|  * the Free Software Foundation; either version 2.1 of the License, or (at | ||||
|  * your option) any later version. | ||||
|  * | ||||
|  * This library is distributed in the hope that it will be useful, but | ||||
|  * WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser | ||||
|  * General Public License for more details. | ||||
|  * | ||||
|  * You should have received a copy of the GNU Lesser General Public License | ||||
|  * along with this library; if not, write to the Free Software Foundation, | ||||
|  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA | ||||
|  */ | ||||
| 
 | ||||
| #ifdef NDEBUG /* Enable assert always. */ | ||||
| #undef NDEBUG /* Must undef above assert.h or other that might include it. */ | ||||
| #endif | ||||
| 
 | ||||
| #include "sox_i.h" | ||||
| #include <assert.h> | ||||
| #include <string.h> | ||||
| 
 | ||||
| /* Concurrent Control with "Readers" and "Writers", P.J. Courtois et al, 1971:*/ | ||||
| 
 | ||||
| #if defined HAVE_OPENMP | ||||
| 
 | ||||
| typedef struct { | ||||
|   int readcount, writecount; /* initial value = 0 */ | ||||
|   omp_lock_t mutex_1, mutex_2, mutex_3, w, r; /* initial value = 1 */ | ||||
| } ccrw2_t; /* Problem #2: `writers-preference' */ | ||||
| 
 | ||||
| #define ccrw2_become_reader(p) do {\ | ||||
|   omp_set_lock(&p.mutex_3);\
 | ||||
|     omp_set_lock(&p.r);\
 | ||||
|       omp_set_lock(&p.mutex_1);\
 | ||||
|         if (++p.readcount == 1) omp_set_lock(&p.w);\
 | ||||
|       omp_unset_lock(&p.mutex_1);\
 | ||||
|     omp_unset_lock(&p.r);\
 | ||||
|   omp_unset_lock(&p.mutex_3);\
 | ||||
| } while (0) | ||||
| #define ccrw2_cease_reading(p) do {\ | ||||
|   omp_set_lock(&p.mutex_1);\
 | ||||
|     if (!--p.readcount) omp_unset_lock(&p.w);\
 | ||||
|   omp_unset_lock(&p.mutex_1);\
 | ||||
| } while (0) | ||||
| #define ccrw2_become_writer(p) do {\ | ||||
|   omp_set_lock(&p.mutex_2);\
 | ||||
|     if (++p.writecount == 1) omp_set_lock(&p.r);\
 | ||||
|   omp_unset_lock(&p.mutex_2);\
 | ||||
|   omp_set_lock(&p.w);\
 | ||||
| } while (0) | ||||
| #define ccrw2_cease_writing(p) do {\ | ||||
|   omp_unset_lock(&p.w);\
 | ||||
|   omp_set_lock(&p.mutex_2);\
 | ||||
|     if (!--p.writecount) omp_unset_lock(&p.r);\
 | ||||
|   omp_unset_lock(&p.mutex_2);\
 | ||||
| } while (0) | ||||
| #define ccrw2_init(p) do {\ | ||||
|   omp_init_lock(&p.mutex_1);\
 | ||||
|   omp_init_lock(&p.mutex_2);\
 | ||||
|   omp_init_lock(&p.mutex_3);\
 | ||||
|   omp_init_lock(&p.w);\
 | ||||
|   omp_init_lock(&p.r);\
 | ||||
| } while (0) | ||||
| #define ccrw2_clear(p) do {\ | ||||
|   omp_destroy_lock(&p.r);\
 | ||||
|   omp_destroy_lock(&p.w);\
 | ||||
|   omp_destroy_lock(&p.mutex_3);\
 | ||||
|   omp_destroy_lock(&p.mutex_2);\
 | ||||
|   omp_destroy_lock(&p.mutex_1);\
 | ||||
| } while (0) | ||||
| 
 | ||||
| #else | ||||
| 
 | ||||
| #define ccrw2_become_reader(x) (void)0 | ||||
| #define ccrw2_cease_reading(x) (void)0 | ||||
| #define ccrw2_become_writer(x) (void)0 | ||||
| #define ccrw2_cease_writing(x) (void)0 | ||||
| #define ccrw2_init(x) (void)0 | ||||
| #define ccrw2_clear(x) (void)0 | ||||
| 
 | ||||
| #endif /* HAVE_OPENMP */ | ||||
| 
 | ||||
| /* Numerical Recipes cubic spline: */ | ||||
| 
 | ||||
| void lsx_prepare_spline3(double const * x, double const * y, int n, | ||||
|     double start_1d, double end_1d, double * y_2d) | ||||
| { | ||||
|   double p, qn, sig, un, * u = lsx_malloc((n - 1) * sizeof(*u)); | ||||
|   int i; | ||||
| 
 | ||||
|   if (start_1d == HUGE_VAL) | ||||
|     y_2d[0] = u[0] = 0;      /* Start with natural spline or */ | ||||
|   else {                     /* set the start first derivative */ | ||||
|     y_2d[0] = -.5; | ||||
|     u[0] = (3 / (x[1] - x[0])) * ((y[1] - y[0]) / (x[1] - x[0]) - start_1d); | ||||
|   } | ||||
| 
 | ||||
|   for (i = 1; i < n - 1; ++i) { | ||||
|     sig = (x[i] - x[i - 1]) / (x[i + 1] - x[i - 1]); | ||||
|     p = sig * y_2d[i - 1] + 2; | ||||
|     y_2d[i] = (sig - 1) / p; | ||||
|     u[i] = (y[i + 1] - y[i]) / (x[i + 1] - x[i]) - | ||||
|            (y[i] - y[i - 1]) / (x[i] - x[i - 1]); | ||||
|     u[i] = (6 * u[i] / (x[i + 1] - x[i - 1]) - sig * u[i - 1]) / p; | ||||
|   } | ||||
|   if (end_1d == HUGE_VAL) | ||||
|     qn = un = 0;             /* End with natural spline or */ | ||||
|   else {                     /* set the end first derivative */ | ||||
|     qn = .5; | ||||
|     un = 3 / (x[n - 1] - x[n - 2]) * (end_1d - (y[n - 1] - y[n - 2]) / (x[n - 1] - x[n - 2])); | ||||
|   } | ||||
|   y_2d[n - 1] = (un - qn * u[n - 2]) / (qn * y_2d[n - 2] + 1); | ||||
|   for (i = n - 2; i >= 0; --i) | ||||
|     y_2d[i] = y_2d[i] * y_2d[i + 1] + u[i]; | ||||
|   free(u); | ||||
| } | ||||
| 
 | ||||
| double lsx_spline3(double const * x, double const * y, double const * y_2d, | ||||
|     int n, double x1) | ||||
| { | ||||
|   int     t, i[2] = {0, 0}; | ||||
|   double  d, a, b; | ||||
| 
 | ||||
|   for (i[1] = n - 1; i[1] - i[0] > 1; t = (i[1] + i[0]) >> 1, i[x[t] > x1] = t); | ||||
|   d = x[i[1]] - x[i[0]]; | ||||
|   assert(d != 0); | ||||
|   a = (x[i[1]] - x1) / d; | ||||
|   b = (x1 - x[i[0]]) / d; | ||||
|   return a * y[i[0]] + b * y[i[1]] + | ||||
|     ((a * a * a - a) * y_2d[i[0]] + (b * b * b - b) * y_2d[i[1]]) * d * d / 6; | ||||
| } | ||||
| 
 | ||||
| double lsx_bessel_I_0(double x) | ||||
| { | ||||
|   double term = 1, sum = 1, last_sum, x2 = x / 2; | ||||
|   int i = 1; | ||||
|   do { | ||||
|     double y = x2 / i++; | ||||
|     last_sum = sum, sum += term *= y * y; | ||||
|   } while (sum != last_sum); | ||||
|   return sum; | ||||
| } | ||||
| 
 | ||||
| int lsx_set_dft_length(int num_taps) /* Set to 4 x nearest power of 2 */ | ||||
| {      /* or half of that if danger of causing too many cache misses. */ | ||||
|   int min = sox_globals.log2_dft_min_size; | ||||
|   double d = log((double)num_taps) / log(2.); | ||||
|   return 1 << range_limit((int)(d + 2.77), min, max((int)(d + 1.77), 17)); | ||||
| } | ||||
| 
 | ||||
| #include "fft4g.h" | ||||
| static int * lsx_fft_br; | ||||
| static double * lsx_fft_sc; | ||||
| static int fft_len = -1; | ||||
| #if defined HAVE_OPENMP | ||||
| static ccrw2_t fft_cache_ccrw; | ||||
| #endif | ||||
| 
 | ||||
| void init_fft_cache(void) | ||||
| { | ||||
|   assert(lsx_fft_br == NULL); | ||||
|   assert(lsx_fft_sc == NULL); | ||||
|   assert(fft_len == -1); | ||||
|   ccrw2_init(fft_cache_ccrw); | ||||
|   fft_len = 0; | ||||
| } | ||||
| 
 | ||||
| void clear_fft_cache(void) | ||||
| { | ||||
|   assert(fft_len >= 0); | ||||
|   ccrw2_clear(fft_cache_ccrw); | ||||
|   free(lsx_fft_br); | ||||
|   free(lsx_fft_sc); | ||||
|   lsx_fft_sc = NULL; | ||||
|   lsx_fft_br = NULL; | ||||
|   fft_len = -1; | ||||
| } | ||||
| 
 | ||||
| static sox_bool update_fft_cache(int len) | ||||
| { | ||||
|   assert(lsx_is_power_of_2(len)); | ||||
|   assert(fft_len >= 0); | ||||
|   ccrw2_become_reader(fft_cache_ccrw); | ||||
|   if (len > fft_len) { | ||||
|     ccrw2_cease_reading(fft_cache_ccrw); | ||||
|     ccrw2_become_writer(fft_cache_ccrw); | ||||
|     if (len > fft_len) { | ||||
|       int old_n = fft_len; | ||||
|       fft_len = len; | ||||
|       lsx_fft_br = lsx_realloc(lsx_fft_br, dft_br_len(fft_len) * sizeof(*lsx_fft_br)); | ||||
|       lsx_fft_sc = lsx_realloc(lsx_fft_sc, dft_sc_len(fft_len) * sizeof(*lsx_fft_sc)); | ||||
|       if (!old_n) | ||||
|         lsx_fft_br[0] = 0; | ||||
|       return sox_true; | ||||
|     } | ||||
|     ccrw2_cease_writing(fft_cache_ccrw); | ||||
|     ccrw2_become_reader(fft_cache_ccrw); | ||||
|   } | ||||
|   return sox_false; | ||||
| } | ||||
| 
 | ||||
| static void done_with_fft_cache(sox_bool is_writer) | ||||
| { | ||||
|   if (is_writer) | ||||
|     ccrw2_cease_writing(fft_cache_ccrw); | ||||
|   else ccrw2_cease_reading(fft_cache_ccrw); | ||||
| } | ||||
| 
 | ||||
| void lsx_safe_rdft(int len, int type, double * d) | ||||
| { | ||||
|   sox_bool is_writer = update_fft_cache(len); | ||||
|   lsx_rdft(len, type, d, lsx_fft_br, lsx_fft_sc); | ||||
|   done_with_fft_cache(is_writer); | ||||
| } | ||||
| 
 | ||||
| void lsx_safe_cdft(int len, int type, double * d) | ||||
| { | ||||
|   sox_bool is_writer = update_fft_cache(len); | ||||
|   lsx_cdft(len, type, d, lsx_fft_br, lsx_fft_sc); | ||||
|   done_with_fft_cache(is_writer); | ||||
| } | ||||
| 
 | ||||
| void lsx_power_spectrum(int n, double const * in, double * out) | ||||
| { | ||||
|   int i; | ||||
|   double * work = lsx_memdup(in, n * sizeof(*work)); | ||||
|   lsx_safe_rdft(n, 1, work); | ||||
|   out[0] = sqr(work[0]); | ||||
|   for (i = 2; i < n; i += 2) | ||||
|     out[i >> 1] = sqr(work[i]) + sqr(work[i + 1]); | ||||
|   out[i >> 1] = sqr(work[1]); | ||||
|   free(work); | ||||
| } | ||||
| 
 | ||||
| void lsx_power_spectrum_f(int n, float const * in, float * out) | ||||
| { | ||||
|   int i; | ||||
|   double * work = lsx_malloc(n * sizeof(*work)); | ||||
|   for (i = 0; i< n; ++i) work[i] = in[i]; | ||||
|   lsx_safe_rdft(n, 1, work); | ||||
|   out[0] = sqr(work[0]); | ||||
|   for (i = 2; i < n; i += 2) | ||||
|     out[i >> 1] = sqr(work[i]) + sqr(work[i + 1]); | ||||
|   out[i >> 1] = sqr(work[1]); | ||||
|   free(work); | ||||
| } | ||||
| 
 | ||||
| void lsx_apply_hann_f(float h[], const int num_points) | ||||
| { | ||||
|   int i, m = num_points - 1; | ||||
|   for (i = 0; i < num_points; ++i) { | ||||
|     double x = 2 * M_PI * i / m; | ||||
|     h[i] *= .5 - .5 * cos(x); | ||||
|   } | ||||
| } | ||||
| 
 | ||||
| void lsx_apply_hann(double h[], const int num_points) | ||||
| { | ||||
|   int i, m = num_points - 1; | ||||
|   for (i = 0; i < num_points; ++i) { | ||||
|     double x = 2 * M_PI * i / m; | ||||
|     h[i] *= .5 - .5 * cos(x); | ||||
|   } | ||||
| } | ||||
| 
 | ||||
| void lsx_apply_hamming(double h[], const int num_points) | ||||
| { | ||||
|   int i, m = num_points - 1; | ||||
|   for (i = 0; i < num_points; ++i) { | ||||
|     double x = 2 * M_PI * i / m; | ||||
|     h[i] *= .53836 - .46164 * cos(x); | ||||
|   } | ||||
| } | ||||
| 
 | ||||
| void lsx_apply_bartlett(double h[], const int num_points) | ||||
| { | ||||
|   int i, m = num_points - 1; | ||||
|   for (i = 0; i < num_points; ++i) { | ||||
|     h[i] *= 2. / m * (m / 2. - fabs(i - m / 2.)); | ||||
|   } | ||||
| } | ||||
| 
 | ||||
| void lsx_apply_blackman(double h[], const int num_points, double alpha /*.16*/) | ||||
| { | ||||
|   int i, m = num_points - 1; | ||||
|   for (i = 0; i < num_points; ++i) { | ||||
|     double x = 2 * M_PI * i / m; | ||||
|     h[i] *= (1 - alpha) *.5 - .5 * cos(x) + alpha * .5 * cos(2 * x); | ||||
|   } | ||||
| } | ||||
| 
 | ||||
| void lsx_apply_blackman_nutall(double h[], const int num_points) | ||||
| { | ||||
|   int i, m = num_points - 1; | ||||
|   for (i = 0; i < num_points; ++i) { | ||||
|     double x = 2 * M_PI * i / m; | ||||
|     h[i] *= .3635819 - .4891775 * cos(x) + .1365995 * cos(2 * x) - .0106411 * cos(3 * x); | ||||
|   } | ||||
| } | ||||
| 
 | ||||
| double lsx_kaiser_beta(double att, double tr_bw) | ||||
| { | ||||
|   if (att >= 60) { | ||||
|     static const double coefs[][4] = { | ||||
|       {-6.784957e-10,1.02856e-05,0.1087556,-0.8988365+.001}, | ||||
|       {-6.897885e-10,1.027433e-05,0.10876,-0.8994658+.002}, | ||||
|       {-1.000683e-09,1.030092e-05,0.1087677,-0.9007898+.003}, | ||||
|       {-3.654474e-10,1.040631e-05,0.1087085,-0.8977766+.006}, | ||||
|       {8.106988e-09,6.983091e-06,0.1091387,-0.9172048+.015}, | ||||
|       {9.519571e-09,7.272678e-06,0.1090068,-0.9140768+.025}, | ||||
|       {-5.626821e-09,1.342186e-05,0.1083999,-0.9065452+.05}, | ||||
|       {-9.965946e-08,5.073548e-05,0.1040967,-0.7672778+.085}, | ||||
|       {1.604808e-07,-5.856462e-05,0.1185998,-1.34824+.1}, | ||||
|       {-1.511964e-07,6.363034e-05,0.1064627,-0.9876665+.18}, | ||||
|     }; | ||||
|     double realm = log(tr_bw/.0005)/log(2.); | ||||
|     double const * c0 = coefs[range_limit(  (int)realm, 0, (int)array_length(coefs)-1)]; | ||||
|     double const * c1 = coefs[range_limit(1+(int)realm, 0, (int)array_length(coefs)-1)]; | ||||
|     double b0 = ((c0[0]*att + c0[1])*att + c0[2])*att + c0[3]; | ||||
|     double b1 = ((c1[0]*att + c1[1])*att + c1[2])*att + c1[3]; | ||||
|     return b0 + (b1 - b0) * (realm - (int)realm); | ||||
|   } | ||||
|   if (att > 50   ) return .1102 * (att - 8.7); | ||||
|   if (att > 20.96) return .58417 * pow(att -20.96, .4) + .07886 * (att - 20.96); | ||||
|   return 0; | ||||
| } | ||||
| 
 | ||||
| void lsx_apply_kaiser(double h[], const int num_points, double beta) | ||||
| { | ||||
|   int i, m = num_points - 1; | ||||
|   for (i = 0; i <= m; ++i) { | ||||
|     double x = 2. * i / m - 1; | ||||
|     h[i] *= lsx_bessel_I_0(beta * sqrt(1 - x * x)) / lsx_bessel_I_0(beta); | ||||
|   } | ||||
| } | ||||
| 
 | ||||
| void lsx_apply_dolph(double h[], const int N, double att) | ||||
| { | ||||
|   double b = cosh(acosh(pow(10., att/20)) / (N-1)), sum, t, c, norm = 0; | ||||
|   int i, j; | ||||
|   for (c = 1 - 1 / (b*b), i = (N-1) / 2; i >= 0; --i) { | ||||
|     for (sum = !i, b = t = j = 1; j <= i && sum != t; b *= (i-j) * (1./j), ++j) | ||||
|       t = sum, sum += (b *= c * (N - i - j) * (1./j)); | ||||
|     sum /= (N - 1 - i), sum /= (norm = norm? norm : sum); | ||||
|     h[i] *= sum, h[N - 1 - i] *= sum; | ||||
|   } | ||||
| } | ||||
| 
 | ||||
| double * lsx_make_lpf(int num_taps, double Fc, double beta, double rho, | ||||
|     double scale, sox_bool dc_norm) | ||||
| { | ||||
|   int i, m = num_taps - 1; | ||||
|   double * h = calloc(num_taps, sizeof(*h)), sum = 0; | ||||
|   double mult = scale / lsx_bessel_I_0(beta), mult1 = 1 / (.5 * m + rho); | ||||
|   assert(Fc >= 0 && Fc <= 1); | ||||
|   lsx_debug("make_lpf(n=%i Fc=%.7g β=%g ρ=%g dc-norm=%i scale=%g)", num_taps, Fc, beta, rho, dc_norm, scale); | ||||
| 
 | ||||
|   if (!h) | ||||
|     return NULL; | ||||
| 
 | ||||
|   for (i = 0; i <= m / 2; ++i) { | ||||
|     double z = i - .5 * m, x = z * M_PI, y = z * mult1; | ||||
|     h[i] = x? sin(Fc * x) / x : Fc; | ||||
|     sum += h[i] *= lsx_bessel_I_0(beta * sqrt(1 - y * y)) * mult; | ||||
|     if (m - i != i) | ||||
|       sum += h[m - i] = h[i]; | ||||
|   } | ||||
|   for (i = 0; dc_norm && i < num_taps; ++i) h[i] *= scale / sum; | ||||
|   return h; | ||||
| } | ||||
| 
 | ||||
| void lsx_kaiser_params(double att, double Fc, double tr_bw, double * beta, int * num_taps) | ||||
| { | ||||
|   *beta = *beta < 0? lsx_kaiser_beta(att, tr_bw * .5 / Fc): *beta; | ||||
|   att = att < 60? (att - 7.95) / (2.285 * M_PI * 2) : | ||||
|     ((.0007528358-1.577737e-05**beta)**beta+.6248022)**beta+.06186902; | ||||
|   *num_taps = !*num_taps? ceil(att/tr_bw + 1) : *num_taps; | ||||
| } | ||||
| 
 | ||||
| double * lsx_design_lpf( | ||||
|     double Fp,      /* End of pass-band */ | ||||
|     double Fs,      /* Start of stop-band */ | ||||
|     double Fn,      /* Nyquist freq; e.g. 0.5, 1, PI */ | ||||
|     double att,     /* Stop-band attenuation in dB */ | ||||
|     int * num_taps, /* 0: value will be estimated */ | ||||
|     int k,          /* >0: number of phases; <0: num_taps ≡ 1 (mod -k) */ | ||||
|     double beta)    /* <0: value will be estimated */ | ||||
| { | ||||
|   int n = *num_taps, phases = max(k, 1), modulo = max(-k, 1); | ||||
|   double tr_bw, Fc, rho = phases == 1? .5 : att < 120? .63 : .75; | ||||
| 
 | ||||
|   Fp /= fabs(Fn), Fs /= fabs(Fn);        /* Normalise to Fn = 1 */ | ||||
|   tr_bw = .5 * (Fs - Fp); /* Transition band-width: 6dB to stop points */ | ||||
|   tr_bw /= phases, Fs /= phases; | ||||
|   tr_bw = min(tr_bw, .5 * Fs); | ||||
|   Fc = Fs - tr_bw; | ||||
|   assert(Fc - tr_bw >= 0); | ||||
|   lsx_kaiser_params(att, Fc, tr_bw, &beta, num_taps); | ||||
|   if (!n) | ||||
|     *num_taps = phases > 1? *num_taps / phases * phases + phases - 1 : (*num_taps + modulo - 2) / modulo * modulo + 1; | ||||
|   return Fn < 0? 0 : lsx_make_lpf( | ||||
|       *num_taps, Fc, beta, rho, (double)phases, sox_false); | ||||
| } | ||||
| 
 | ||||
| static double safe_log(double x) | ||||
| { | ||||
|   assert(x >= 0); | ||||
|   if (x) | ||||
|     return log(x); | ||||
|   lsx_debug("log(0)"); | ||||
|   return -26; | ||||
| } | ||||
| 
 | ||||
| void lsx_fir_to_phase(double * * h, int * len, int * post_len, double phase) | ||||
| { | ||||
|   double * pi_wraps, * work, phase1 = (phase > 50 ? 100 - phase : phase) / 50; | ||||
|   int i, work_len, begin, end, imp_peak = 0, peak = 0; | ||||
|   double imp_sum = 0, peak_imp_sum = 0; | ||||
|   double prev_angle2 = 0, cum_2pi = 0, prev_angle1 = 0, cum_1pi = 0; | ||||
| 
 | ||||
|   for (i = *len, work_len = 2 * 2 * 8; i > 1; work_len <<= 1, i >>= 1); | ||||
| 
 | ||||
|   work = lsx_calloc((size_t)work_len + 2, sizeof(*work)); /* +2: (UN)PACK */ | ||||
|   pi_wraps = lsx_malloc((((size_t)work_len + 2) / 2) * sizeof(*pi_wraps)); | ||||
| 
 | ||||
|   memcpy(work, *h, *len * sizeof(*work)); | ||||
|   lsx_safe_rdft(work_len, 1, work); /* Cepstral: */ | ||||
|   LSX_UNPACK(work, work_len); | ||||
| 
 | ||||
|   for (i = 0; i <= work_len; i += 2) { | ||||
|     double angle = atan2(work[i + 1], work[i]); | ||||
|     double detect = 2 * M_PI; | ||||
|     double delta = angle - prev_angle2; | ||||
|     double adjust = detect * ((delta < -detect * .7) - (delta > detect * .7)); | ||||
|     prev_angle2 = angle; | ||||
|     cum_2pi += adjust; | ||||
|     angle += cum_2pi; | ||||
|     detect = M_PI; | ||||
|     delta = angle - prev_angle1; | ||||
|     adjust = detect * ((delta < -detect * .7) - (delta > detect * .7)); | ||||
|     prev_angle1 = angle; | ||||
|     cum_1pi += fabs(adjust); /* fabs for when 2pi and 1pi have combined */ | ||||
|     pi_wraps[i >> 1] = cum_1pi; | ||||
| 
 | ||||
|     work[i] = safe_log(sqrt(sqr(work[i]) + sqr(work[i + 1]))); | ||||
|     work[i + 1] = 0; | ||||
|   } | ||||
|   LSX_PACK(work, work_len); | ||||
|   lsx_safe_rdft(work_len, -1, work); | ||||
|   for (i = 0; i < work_len; ++i) work[i] *= 2. / work_len; | ||||
| 
 | ||||
|   for (i = 1; i < work_len / 2; ++i) { /* Window to reject acausal components */ | ||||
|     work[i] *= 2; | ||||
|     work[i + work_len / 2] = 0; | ||||
|   } | ||||
|   lsx_safe_rdft(work_len, 1, work); | ||||
| 
 | ||||
|   for (i = 2; i < work_len; i += 2) /* Interpolate between linear & min phase */ | ||||
|     work[i + 1] = phase1 * i / work_len * pi_wraps[work_len >> 1] + | ||||
|         (1 - phase1) * (work[i + 1] + pi_wraps[i >> 1]) - pi_wraps[i >> 1]; | ||||
| 
 | ||||
|   work[0] = exp(work[0]), work[1] = exp(work[1]); | ||||
|   for (i = 2; i < work_len; i += 2) { | ||||
|     double x = exp(work[i]); | ||||
|     work[i    ] = x * cos(work[i + 1]); | ||||
|     work[i + 1] = x * sin(work[i + 1]); | ||||
|   } | ||||
| 
 | ||||
|   lsx_safe_rdft(work_len, -1, work); | ||||
|   for (i = 0; i < work_len; ++i) work[i] *= 2. / work_len; | ||||
| 
 | ||||
|   /* Find peak pos. */ | ||||
|   for (i = 0; i <= (int)(pi_wraps[work_len >> 1] / M_PI + .5); ++i) { | ||||
|     imp_sum += work[i]; | ||||
|     if (fabs(imp_sum) > fabs(peak_imp_sum)) { | ||||
|       peak_imp_sum = imp_sum; | ||||
|       peak = i; | ||||
|     } | ||||
|     if (work[i] > work[imp_peak]) /* For debug check only */ | ||||
|       imp_peak = i; | ||||
|   } | ||||
|   while (peak && fabs(work[peak-1]) > fabs(work[peak]) && work[peak-1] * work[peak] > 0) | ||||
|     --peak; | ||||
| 
 | ||||
|   if (!phase1) | ||||
|     begin = 0; | ||||
|   else if (phase1 == 1) | ||||
|     begin = peak - *len / 2; | ||||
|   else { | ||||
|     begin = (.997 - (2 - phase1) * .22) * *len + .5; | ||||
|     end   = (.997 + (0 - phase1) * .22) * *len + .5; | ||||
|     begin = peak - (begin & ~3); | ||||
|     end   = peak + 1 + ((end + 3) & ~3); | ||||
|     *len = end - begin; | ||||
|     *h = lsx_realloc(*h, *len * sizeof(**h)); | ||||
|   } | ||||
|   for (i = 0; i < *len; ++i) (*h)[i] = | ||||
|     work[(begin + (phase > 50 ? *len - 1 - i : i) + work_len) & (work_len - 1)]; | ||||
|   *post_len = phase > 50 ? peak - begin : begin + *len - (peak + 1); | ||||
| 
 | ||||
|   lsx_debug("nPI=%g peak-sum@%i=%g (val@%i=%g); len=%i post=%i (%g%%)", | ||||
|       pi_wraps[work_len >> 1] / M_PI, peak, peak_imp_sum, imp_peak, | ||||
|       work[imp_peak], *len, *post_len, 100 - 100. * *post_len / (*len - 1)); | ||||
|   free(pi_wraps), free(work); | ||||
| } | ||||
| 
 | ||||
| void lsx_plot_fir(double * h, int num_points, sox_rate_t rate, sox_plot_t type, char const * title, double y1, double y2) | ||||
| { | ||||
|   int i, N = lsx_set_dft_length(num_points); | ||||
|   if (type == sox_plot_gnuplot) { | ||||
|     double * h1 = lsx_calloc(N, sizeof(*h1)); | ||||
|     double * H = lsx_malloc((N / 2 + 1) * sizeof(*H)); | ||||
|     memcpy(h1, h, sizeof(*h1) * num_points); | ||||
|     lsx_power_spectrum(N, h1, H); | ||||
|     printf( | ||||
|         "# gnuplot file\n" | ||||
|         "set title '%s'\n" | ||||
|         "set xlabel 'Frequency (Hz)'\n" | ||||
|         "set ylabel 'Amplitude Response (dB)'\n" | ||||
|         "set grid xtics ytics\n" | ||||
|         "set key off\n" | ||||
|         "plot '-' with lines\n" | ||||
|         , title); | ||||
|     for (i = 0; i <= N/2; ++i) | ||||
|       printf("%g %g\n", i * rate / N, 10 * log10(H[i])); | ||||
|     printf( | ||||
|         "e\n" | ||||
|         "pause -1 'Hit return to continue'\n"); | ||||
|     free(H); | ||||
|     free(h1); | ||||
|   } | ||||
|   else if (type == sox_plot_octave) { | ||||
|     printf("%% GNU Octave file (may also work with MATLAB(R) )\nb=["); | ||||
|     for (i = 0; i < num_points; ++i) | ||||
|       printf("%24.16e\n", h[i]); | ||||
|     printf("];\n" | ||||
|         "[h,w]=freqz(b,1,%i);\n" | ||||
|         "plot(%g*w/pi,20*log10(h))\n" | ||||
|         "title('%s')\n" | ||||
|         "xlabel('Frequency (Hz)')\n" | ||||
|         "ylabel('Amplitude Response (dB)')\n" | ||||
|         "grid on\n" | ||||
|         "axis([0 %g %g %g])\n" | ||||
|         "disp('Hit return to continue')\n" | ||||
|         "pause\n" | ||||
|         , N, rate * .5, title, rate * .5, y1, y2); | ||||
|   } | ||||
|   else if (type == sox_plot_data) { | ||||
|     printf("# %s\n" | ||||
|         "# FIR filter\n" | ||||
|         "# rate: %g\n" | ||||
|         "# name: b\n" | ||||
|         "# type: matrix\n" | ||||
|         "# rows: %i\n" | ||||
|         "# columns: 1\n", title, rate, num_points); | ||||
|     for (i = 0; i < num_points; ++i) | ||||
|       printf("%24.16e\n", h[i]); | ||||
|   } | ||||
| } | ||||
| 
 | ||||
| #if HAVE_FENV_H | ||||
|   #include <fenv.h> | ||||
|   #if defined FE_INVALID | ||||
|     #if HAVE_LRINT && LONG_MAX == 2147483647 | ||||
|       #define lrint32 lrint | ||||
|     #elif defined __GNUC__ && defined __x86_64__ | ||||
|       #define lrint32 lrint32 | ||||
|       static __inline sox_int32_t lrint32(double input) { | ||||
|         sox_int32_t result; | ||||
|         __asm__ __volatile__("fistpl %0": "=m"(result): "t"(input): "st"); | ||||
|         return result; | ||||
|       } | ||||
|     #endif | ||||
|   #endif | ||||
| #endif | ||||
| 
 | ||||
| #if defined lrint32 | ||||
| #define _ dest[i] = lrint32(src[i]), ++i, | ||||
| #pragma STDC FENV_ACCESS ON | ||||
| 
 | ||||
| static void rint_clip(sox_sample_t * const dest, double const * const src, | ||||
|     size_t i, size_t const n, sox_uint64_t * const clips) | ||||
| { | ||||
|   for (; i < n; ++i) { | ||||
|     dest[i] = lrint32(src[i]); | ||||
|     if (fetestexcept(FE_INVALID)) { | ||||
|       feclearexcept(FE_INVALID); | ||||
|       dest[i] = src[i] > 0? SOX_SAMPLE_MAX : SOX_SAMPLE_MIN; | ||||
|       ++*clips; | ||||
|     } | ||||
|   } | ||||
| } | ||||
| 
 | ||||
| void lsx_save_samples(sox_sample_t * const dest, double const * const src, | ||||
|     size_t const n, sox_uint64_t * const clips) | ||||
| { | ||||
|   size_t i; | ||||
|   feclearexcept(FE_INVALID); | ||||
|   for (i = 0; i < (n & ~7);) { | ||||
|     _ _ _ _ _ _ _ _ 0; | ||||
|     if (fetestexcept(FE_INVALID)) { | ||||
|       feclearexcept(FE_INVALID); | ||||
|       rint_clip(dest, src, i - 8, i, clips); | ||||
|     } | ||||
|   } | ||||
|   rint_clip(dest, src, i, n, clips); | ||||
| } | ||||
| 
 | ||||
| void lsx_load_samples(double * const dest, sox_sample_t const * const src, | ||||
|     size_t const n) | ||||
| { | ||||
|   size_t i; | ||||
|   for (i = 0; i < n; ++i) | ||||
|     dest[i] = src[i]; | ||||
| } | ||||
| 
 | ||||
| #pragma STDC FENV_ACCESS OFF | ||||
| #undef _ | ||||
| #else | ||||
| 
 | ||||
| void lsx_save_samples(sox_sample_t * const dest, double const * const src, | ||||
|     size_t const n, sox_uint64_t * const clips) | ||||
| { | ||||
|   SOX_SAMPLE_LOCALS; | ||||
|   size_t i; | ||||
|   for (i = 0; i < n; ++i) | ||||
|     dest[i] = SOX_FLOAT_64BIT_TO_SAMPLE(src[i], *clips); | ||||
| } | ||||
| 
 | ||||
| void lsx_load_samples(double * const dest, sox_sample_t const * const src, | ||||
|     size_t const n) | ||||
| { | ||||
|   size_t i; | ||||
|   for (i = 0; i < n; ++i) | ||||
|     dest[i] = SOX_SAMPLE_TO_FLOAT_64BIT(src[i],); | ||||
| } | ||||
| 
 | ||||
| #endif | ||||
| @ -1,102 +0,0 @@ | ||||
| /* Simple example of using SoX libraries
 | ||||
|  * | ||||
|  * Copyright (c) 2007-8 robs@users.sourceforge.net | ||||
|  * | ||||
|  * This program is free software; you can redistribute it and/or modify it | ||||
|  * under the terms of the GNU General Public License as published by the | ||||
|  * Free Software Foundation; either version 2 of the License, or (at your | ||||
|  * option) any later version. | ||||
|  * | ||||
|  * This program is distributed in the hope that it will be useful, but | ||||
|  * WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General | ||||
|  * Public License for more details. | ||||
|  * | ||||
|  * You should have received a copy of the GNU General Public License along | ||||
|  * with this program; if not, write to the Free Software Foundation, Inc., | ||||
|  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. | ||||
|  */ | ||||
| 
 | ||||
| #ifdef NDEBUG /* N.B. assert used with active statements so enable always. */ | ||||
| #undef NDEBUG /* Must undef above assert.h or other that might include it. */ | ||||
| #endif | ||||
| 
 | ||||
| #include "sox.h" | ||||
| #include <stdlib.h> | ||||
| #include <stdio.h> | ||||
| #include <assert.h> | ||||
| 
 | ||||
| /*
 | ||||
|  * Reads input file, applies vol & flanger effects, stores in output file. | ||||
|  * E.g. example1 monkey.au monkey.aiff | ||||
|  */ | ||||
| int main(int argc, char * argv[]) | ||||
| { | ||||
|   static sox_format_t * in, * out; /* input and output files */ | ||||
|   sox_effects_chain_t * chain; | ||||
|   sox_effect_t * e; | ||||
|   char * args[10]; | ||||
| 
 | ||||
|   assert(argc == 3); | ||||
| 
 | ||||
|   /* All libSoX applications must start by initialising the SoX library */ | ||||
|   assert(sox_init() == SOX_SUCCESS); | ||||
| 
 | ||||
|   /* Open the input file (with default parameters) */ | ||||
|   assert((in = sox_open_read(argv[1], NULL, NULL, NULL))); | ||||
| 
 | ||||
|   /* Open the output file; we must specify the output signal characteristics.
 | ||||
|    * Since we are using only simple effects, they are the same as the input | ||||
|    * file characteristics */ | ||||
|   assert((out = sox_open_write(argv[2], &in->signal, NULL, NULL, NULL, NULL))); | ||||
| 
 | ||||
|   /* Create an effects chain; some effects need to know about the input
 | ||||
|    * or output file encoding so we provide that information here */ | ||||
|   chain = sox_create_effects_chain(&in->encoding, &out->encoding); | ||||
| 
 | ||||
|   /* The first effect in the effect chain must be something that can source
 | ||||
|    * samples; in this case, we use the built-in handler that inputs | ||||
|    * data from an audio file */ | ||||
|   e = sox_create_effect(sox_find_effect("input")); | ||||
|   args[0] = (char *)in, assert(sox_effect_options(e, 1, args) == SOX_SUCCESS); | ||||
|   /* This becomes the first `effect' in the chain */ | ||||
|   assert(sox_add_effect(chain, e, &in->signal, &in->signal) == SOX_SUCCESS); | ||||
|   free(e); | ||||
| 
 | ||||
|   /* Create the `vol' effect, and initialise it with the desired parameters: */ | ||||
|   e = sox_create_effect(sox_find_effect("vol")); | ||||
|   args[0] = "3dB", assert(sox_effect_options(e, 1, args) == SOX_SUCCESS); | ||||
|   /* Add the effect to the end of the effects processing chain: */ | ||||
|   assert(sox_add_effect(chain, e, &in->signal, &in->signal) == SOX_SUCCESS); | ||||
|   free(e); | ||||
| 
 | ||||
|   args[0] = "--wet-only"; | ||||
|   args[1] = "50";  // reverberance [0, 100] 50%
 | ||||
|   args[2] = "50";  // hf_damping [0, 100] 50%
 | ||||
|   args[3] = "100"; // room_scale [0, 100] 100%
 | ||||
|   args[4] = "100"; // stereo_depth [0, 100] 100%
 | ||||
|   args[5] = "0";   // pre_delay_ms [0, 500] 0ms
 | ||||
|   args[6] = "0";   // wet_gain_dB [-10, 10] 0dB
 | ||||
|   e = sox_create_effect(sox_find_effect("reverb")); | ||||
|   assert(sox_effect_options(e, 7, args) == SOX_SUCCESS); | ||||
|   assert(sox_add_effect(chain, e, &in->signal, &in->signal) == SOX_SUCCESS); | ||||
|   free(e); | ||||
| 
 | ||||
|   /* The last effect in the effect chain must be something that only consumes
 | ||||
|    * samples; in this case, we use the built-in handler that outputs | ||||
|    * data to an audio file */ | ||||
|   e = sox_create_effect(sox_find_effect("output")); | ||||
|   args[0] = (char *)out, assert(sox_effect_options(e, 1, args) == SOX_SUCCESS); | ||||
|   assert(sox_add_effect(chain, e, &in->signal, &in->signal) == SOX_SUCCESS); | ||||
|   free(e); | ||||
| 
 | ||||
|   /* Flow samples through the effects processing chain until EOF is reached */ | ||||
|   sox_flow_effects(chain, NULL, NULL); | ||||
| 
 | ||||
|   /* All done; tidy up: */ | ||||
|   sox_delete_effects_chain(chain); | ||||
|   sox_close(out); | ||||
|   sox_close(in); | ||||
|   sox_quit(); | ||||
|   return 0; | ||||
| } | ||||
| @ -1,167 +0,0 @@ | ||||
| /* Simple example of using SoX libraries
 | ||||
|  * | ||||
|  * Copyright (c) 2007-8 robs@users.sourceforge.net | ||||
|  * | ||||
|  * This program is free software; you can redistribute it and/or modify it | ||||
|  * under the terms of the GNU General Public License as published by the | ||||
|  * Free Software Foundation; either version 2 of the License, or (at your | ||||
|  * option) any later version. | ||||
|  * | ||||
|  * This program is distributed in the hope that it will be useful, but | ||||
|  * WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General | ||||
|  * Public License for more details. | ||||
|  * | ||||
|  * You should have received a copy of the GNU General Public License along | ||||
|  * with this program; if not, write to the Free Software Foundation, Inc., | ||||
|  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. | ||||
|  */ | ||||
| 
 | ||||
| #ifdef NDEBUG /* N.B. assert used with active statements so enable always. */ | ||||
| #undef NDEBUG /* Must undef above assert.h or other that might include it. */ | ||||
| #endif | ||||
| 
 | ||||
| #include "sox.h" | ||||
| #include <stdlib.h> | ||||
| #include <stdio.h> | ||||
| #include <assert.h> | ||||
| 
 | ||||
| static sox_format_t * in, * out; /* input and output files */ | ||||
| 
 | ||||
| /* The function that will be called to input samples into the effects chain.
 | ||||
|  * In this example, we get samples to process from a SoX-openned audio file. | ||||
|  * In a different application, they might be generated or come from a different | ||||
|  * part of the application. */ | ||||
| static int input_drain( | ||||
|     sox_effect_t * effp, sox_sample_t * obuf, size_t * osamp) | ||||
| { | ||||
|   (void)effp;   /* This parameter is not needed in this example */ | ||||
| 
 | ||||
|   /* ensure that *osamp is a multiple of the number of channels. */ | ||||
|   *osamp -= *osamp % effp->out_signal.channels; | ||||
| 
 | ||||
|   /* Read up to *osamp samples into obuf; store the actual number read
 | ||||
|    * back to *osamp */ | ||||
|   *osamp = sox_read(in, obuf, *osamp); | ||||
| 
 | ||||
|   /* sox_read may return a number that is less than was requested; only if
 | ||||
|    * 0 samples is returned does it indicate that end-of-file has been reached | ||||
|    * or an error has occurred */ | ||||
|   if (!*osamp && in->sox_errno) | ||||
|     fprintf(stderr, "%s: %s\n", in->filename, in->sox_errstr); | ||||
|   return *osamp? SOX_SUCCESS : SOX_EOF; | ||||
| } | ||||
| 
 | ||||
| /* The function that will be called to output samples from the effects chain.
 | ||||
|  * In this example, we store the samples in a SoX-opened audio file. | ||||
|  * In a different application, they might perhaps be analysed in some way, | ||||
|  * or displayed as a wave-form */ | ||||
| static int output_flow(sox_effect_t *effp LSX_UNUSED, sox_sample_t const * ibuf, | ||||
|     sox_sample_t * obuf LSX_UNUSED, size_t * isamp, size_t * osamp) | ||||
| { | ||||
|   /* Write out *isamp samples */ | ||||
|   size_t len = sox_write(out, ibuf, *isamp); | ||||
| 
 | ||||
|   /* len is the number of samples that were actually written out; if this is
 | ||||
|    * different to *isamp, then something has gone wrong--most often, it's | ||||
|    * out of disc space */ | ||||
|   if (len != *isamp) { | ||||
|     fprintf(stderr, "%s: %s\n", out->filename, out->sox_errstr); | ||||
|     return SOX_EOF; | ||||
|   } | ||||
| 
 | ||||
|   /* Outputting is the last `effect' in the effect chain so always passes
 | ||||
|    * 0 samples on to the next effect (as there isn't one!) */ | ||||
|   *osamp = 0; | ||||
| 
 | ||||
|   (void)effp;   /* This parameter is not needed in this example */ | ||||
| 
 | ||||
|   return SOX_SUCCESS; /* All samples output successfully */ | ||||
| } | ||||
| 
 | ||||
| /* A `stub' effect handler to handle inputting samples to the effects
 | ||||
|  * chain; the only function needed for this example is `drain' */ | ||||
| static sox_effect_handler_t const * input_handler(void) | ||||
| { | ||||
|   static sox_effect_handler_t handler = { | ||||
|     "input", NULL, SOX_EFF_MCHAN, NULL, NULL, NULL, input_drain, NULL, NULL, 0 | ||||
|   }; | ||||
|   return &handler; | ||||
| } | ||||
| 
 | ||||
| /* A `stub' effect handler to handle outputting samples from the effects
 | ||||
|  * chain; the only function needed for this example is `flow' */ | ||||
| static sox_effect_handler_t const * output_handler(void) | ||||
| { | ||||
|   static sox_effect_handler_t handler = { | ||||
|     "output", NULL, SOX_EFF_MCHAN, NULL, NULL, output_flow, NULL, NULL, NULL, 0 | ||||
|   }; | ||||
|   return &handler; | ||||
| } | ||||
| 
 | ||||
| /*
 | ||||
|  * Reads input file, applies vol & flanger effects, stores in output file. | ||||
|  * E.g. example1 monkey.au monkey.aiff | ||||
|  */ | ||||
| int main(int argc, char * argv[]) | ||||
| { | ||||
|   sox_effects_chain_t * chain; | ||||
|   sox_effect_t * e; | ||||
|   char * vol[] = {"3dB"}; | ||||
| 
 | ||||
|   assert(argc == 3); | ||||
| 
 | ||||
|   /* All libSoX applications must start by initialising the SoX library */ | ||||
|   assert(sox_init() == SOX_SUCCESS); | ||||
| 
 | ||||
|   /* Open the input file (with default parameters) */ | ||||
|   assert(in = sox_open_read(argv[1], NULL, NULL, NULL)); | ||||
| 
 | ||||
|   /* Open the output file; we must specify the output signal characteristics.
 | ||||
|    * Since we are using only simple effects, they are the same as the input | ||||
|    * file characteristics */ | ||||
|   assert(out = sox_open_write(argv[2], &in->signal, NULL, NULL, NULL, NULL)); | ||||
| 
 | ||||
|   /* Create an effects chain; some effects need to know about the input
 | ||||
|    * or output file encoding so we provide that information here */ | ||||
|   chain = sox_create_effects_chain(&in->encoding, &out->encoding); | ||||
| 
 | ||||
|   /* The first effect in the effect chain must be something that can source
 | ||||
|    * samples; in this case, we have defined an input handler that inputs | ||||
|    * data from an audio file */ | ||||
|   e = sox_create_effect(input_handler()); | ||||
|   /* This becomes the first `effect' in the chain */ | ||||
|   assert(sox_add_effect(chain, e, &in->signal, &in->signal) == SOX_SUCCESS); | ||||
|   free(e); | ||||
| 
 | ||||
|   /* Create the `vol' effect, and initialise it with the desired parameters: */ | ||||
|   e = sox_create_effect(sox_find_effect("vol")); | ||||
|   assert(sox_effect_options(e, 1, vol) == SOX_SUCCESS); | ||||
|   /* Add the effect to the end of the effects processing chain: */ | ||||
|   assert(sox_add_effect(chain, e, &in->signal, &in->signal) == SOX_SUCCESS); | ||||
|   free(e); | ||||
| 
 | ||||
|   /* Create the `flanger' effect, and initialise it with default parameters: */ | ||||
|   e = sox_create_effect(sox_find_effect("flanger")); | ||||
|   assert(sox_effect_options(e, 0, NULL) == SOX_SUCCESS); | ||||
|   /* Add the effect to the end of the effects processing chain: */ | ||||
|   assert(sox_add_effect(chain, e, &in->signal, &in->signal) == SOX_SUCCESS); | ||||
|   free(e); | ||||
| 
 | ||||
|   /* The last effect in the effect chain must be something that only consumes
 | ||||
|    * samples; in this case, we have defined an output handler that outputs | ||||
|    * data to an audio file */ | ||||
|   e = sox_create_effect(output_handler()); | ||||
|   assert(sox_add_effect(chain, e, &in->signal, &in->signal) == SOX_SUCCESS); | ||||
|   free(e); | ||||
| 
 | ||||
|   /* Flow samples through the effects processing chain until EOF is reached */ | ||||
|   sox_flow_effects(chain, NULL, NULL); | ||||
| 
 | ||||
|   /* All done; tidy up: */ | ||||
|   sox_delete_effects_chain(chain); | ||||
|   sox_close(out); | ||||
|   sox_close(in); | ||||
|   sox_quit(); | ||||
|   return 0; | ||||
| } | ||||
									
										
											File diff suppressed because it is too large
											Load Diff
										
									
								
							
						| @ -1,37 +0,0 @@ | ||||
| /* This library is free software; you can redistribute it and/or modify it
 | ||||
|  * under the terms of the GNU Lesser General Public License as published by | ||||
|  * the Free Software Foundation; either version 2.1 of the License, or (at | ||||
|  * your option) any later version. | ||||
|  * | ||||
|  * This library is distributed in the hope that it will be useful, but | ||||
|  * WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser | ||||
|  * General Public License for more details. | ||||
|  * | ||||
|  * You should have received a copy of the GNU Lesser General Public License | ||||
|  * along with this library; if not, write to the Free Software Foundation, | ||||
|  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA | ||||
|  */ | ||||
| 
 | ||||
| #define FFT4G_MAX_SIZE 262144 | ||||
| 
 | ||||
| void lsx_cdft(int, int, double *, int *, double *); | ||||
| void lsx_rdft(int, int, double *, int *, double *); | ||||
| void lsx_ddct(int, int, double *, int *, double *); | ||||
| void lsx_ddst(int, int, double *, int *, double *); | ||||
| void lsx_dfct(int, double *, double *, int *, double *); | ||||
| void lsx_dfst(int, double *, double *, int *, double *); | ||||
| 
 | ||||
| void lsx_cdft_f(int, int, float *, int *, float *); | ||||
| void lsx_rdft_f(int, int, float *, int *, float *); | ||||
| void lsx_ddct_f(int, int, float *, int *, float *); | ||||
| void lsx_ddst_f(int, int, float *, int *, float *); | ||||
| void lsx_dfct_f(int, float *, float *, int *, float *); | ||||
| void lsx_dfst_f(int, float *, float *, int *, float *); | ||||
| 
 | ||||
| #define dft_br_len(l) (2 + (1 << (int)(log(l / 2 + .5) / log(2.)) / 2)) | ||||
| #define dft_sc_len(l) (l / 2) | ||||
| 
 | ||||
| /* Over-allocate h by 2 to use these macros */ | ||||
| #define LSX_PACK(h, n)   h[1] = h[n] | ||||
| #define LSX_UNPACK(h, n) h[n] = h[1], h[n + 1] = h[1] = 0; | ||||
| @ -1,119 +0,0 @@ | ||||
| /* Addressable FIFO buffer    Copyright (c) 2007 robs@users.sourceforge.net
 | ||||
|  * | ||||
|  * This library is free software; you can redistribute it and/or modify it | ||||
|  * under the terms of the GNU Lesser General Public License as published by | ||||
|  * the Free Software Foundation; either version 2.1 of the License, or (at | ||||
|  * your option) any later version. | ||||
|  * | ||||
|  * This library is distributed in the hope that it will be useful, but | ||||
|  * WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser | ||||
|  * General Public License for more details. | ||||
|  * | ||||
|  * You should have received a copy of the GNU Lesser General Public License | ||||
|  * along with this library; if not, write to the Free Software Foundation, | ||||
|  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA | ||||
|  */ | ||||
| 
 | ||||
| #ifndef fifo_included | ||||
| #define fifo_included | ||||
| 
 | ||||
| #include <string.h> | ||||
| 
 | ||||
| #ifndef FIFO_SIZE_T | ||||
| #define FIFO_SIZE_T size_t | ||||
| #endif | ||||
| 
 | ||||
| typedef struct { | ||||
|   char * data; | ||||
|   size_t allocation;   /* Number of bytes allocated for data. */ | ||||
|   size_t item_size;    /* Size of each item in data */ | ||||
|   size_t begin;        /* Offset of the first byte to read. */ | ||||
|   size_t end;          /* 1 + Offset of the last byte byte to read. */ | ||||
| } fifo_t; | ||||
| 
 | ||||
| #define FIFO_MIN 0x4000 | ||||
| 
 | ||||
| UNUSED static void fifo_clear(fifo_t * f) | ||||
| { | ||||
|   f->end = f->begin = 0; | ||||
| } | ||||
| 
 | ||||
| UNUSED static void * fifo_reserve(fifo_t * f, FIFO_SIZE_T n) | ||||
| { | ||||
|   n *= f->item_size; | ||||
| 
 | ||||
|   if (f->begin == f->end) | ||||
|     fifo_clear(f); | ||||
| 
 | ||||
|   while (1) { | ||||
|     if (f->end + n <= f->allocation) { | ||||
|       void *p = f->data + f->end; | ||||
| 
 | ||||
|       f->end += n; | ||||
|       return p; | ||||
|     } | ||||
|     if (f->begin > FIFO_MIN) { | ||||
|       memmove(f->data, f->data + f->begin, f->end - f->begin); | ||||
|       f->end -= f->begin; | ||||
|       f->begin = 0; | ||||
|       continue; | ||||
|     } | ||||
|     f->allocation += n; | ||||
|     f->data = lsx_realloc(f->data, f->allocation); | ||||
|   } | ||||
| } | ||||
| 
 | ||||
| UNUSED static void * fifo_write(fifo_t * f, FIFO_SIZE_T n, void const * data) | ||||
| { | ||||
|   void * s = fifo_reserve(f, n); | ||||
|   if (data) | ||||
|     memcpy(s, data, n * f->item_size); | ||||
|   return s; | ||||
| } | ||||
| 
 | ||||
| UNUSED static void fifo_trim_to(fifo_t * f, FIFO_SIZE_T n) | ||||
| { | ||||
|   n *= f->item_size; | ||||
|   f->end = f->begin + n; | ||||
| } | ||||
| 
 | ||||
| UNUSED static void fifo_trim_by(fifo_t * f, FIFO_SIZE_T n) | ||||
| { | ||||
|   n *= f->item_size; | ||||
|   f->end -= n; | ||||
| } | ||||
| 
 | ||||
| UNUSED static FIFO_SIZE_T fifo_occupancy(fifo_t * f) | ||||
| { | ||||
|   return (f->end - f->begin) / f->item_size; | ||||
| } | ||||
| 
 | ||||
| UNUSED static void * fifo_read(fifo_t * f, FIFO_SIZE_T n, void * data) | ||||
| { | ||||
|   char * ret = f->data + f->begin; | ||||
|   n *= f->item_size; | ||||
|   if (n > (FIFO_SIZE_T)(f->end - f->begin)) | ||||
|     return NULL; | ||||
|   if (data) | ||||
|     memcpy(data, ret, (size_t)n); | ||||
|   f->begin += n; | ||||
|   return ret; | ||||
| } | ||||
| 
 | ||||
| #define fifo_read_ptr(f) fifo_read(f, (FIFO_SIZE_T)0, NULL) | ||||
| 
 | ||||
| UNUSED static void fifo_delete(fifo_t * f) | ||||
| { | ||||
|   free(f->data); | ||||
| } | ||||
| 
 | ||||
| UNUSED static void fifo_create(fifo_t * f, FIFO_SIZE_T item_size) | ||||
| { | ||||
|   f->item_size = item_size; | ||||
|   f->allocation = FIFO_MIN; | ||||
|   f->data = lsx_malloc(f->allocation); | ||||
|   fifo_clear(f); | ||||
| } | ||||
| 
 | ||||
| #endif | ||||
									
										
											File diff suppressed because it is too large
											Load Diff
										
									
								
							
						| @ -1,130 +0,0 @@ | ||||
| /* libSoX static formats list   (c) 2006-9 Chris Bagwell and SoX contributors
 | ||||
|  * | ||||
|  * This library is free software; you can redistribute it and/or modify it | ||||
|  * under the terms of the GNU Lesser General Public License as published by | ||||
|  * the Free Software Foundation; either version 2.1 of the License, or (at | ||||
|  * your option) any later version. | ||||
|  * | ||||
|  * This library is distributed in the hope that it will be useful, but | ||||
|  * WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser | ||||
|  * General Public License for more details. | ||||
|  * | ||||
|  * You should have received a copy of the GNU Lesser General Public License | ||||
|  * along with this library; if not, write to the Free Software Foundation, | ||||
|  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA | ||||
|  */ | ||||
| 
 | ||||
| /*-------------------------- Static format handlers --------------------------*/ | ||||
| 
 | ||||
| //  FORMAT(aifc)
 | ||||
| //  FORMAT(aiff)
 | ||||
| //  FORMAT(al)
 | ||||
| //  FORMAT(au)
 | ||||
| //  FORMAT(avr)
 | ||||
| //  FORMAT(cdr)
 | ||||
| //  FORMAT(cvsd)
 | ||||
| //  FORMAT(cvu)
 | ||||
| //  FORMAT(dat)
 | ||||
| //  FORMAT(dvms)
 | ||||
| //  FORMAT(f4)
 | ||||
| //  FORMAT(f8)
 | ||||
| //  FORMAT(gsrt)
 | ||||
| //  FORMAT(hcom)
 | ||||
| //  FORMAT(htk)
 | ||||
| //  FORMAT(ima)
 | ||||
| //  FORMAT(la)
 | ||||
| //  FORMAT(lu)
 | ||||
| //  FORMAT(maud)
 | ||||
| //  FORMAT(nul)
 | ||||
| //  FORMAT(prc)
 | ||||
| //  FORMAT(raw)
 | ||||
| //  FORMAT(s1)
 | ||||
| //  FORMAT(s2)
 | ||||
| //  FORMAT(s3)
 | ||||
| //  FORMAT(s4)
 | ||||
| //  FORMAT(sf)
 | ||||
| //  FORMAT(sln)
 | ||||
| //  FORMAT(smp)
 | ||||
| //  FORMAT(sounder)
 | ||||
| //  FORMAT(soundtool)
 | ||||
| //  FORMAT(sox)
 | ||||
| //  FORMAT(sphere)
 | ||||
| //  FORMAT(svx)
 | ||||
| //  FORMAT(txw)
 | ||||
| //  FORMAT(u1)
 | ||||
| //  FORMAT(u2)
 | ||||
| //  FORMAT(u3)
 | ||||
| //  FORMAT(u4)
 | ||||
| //  FORMAT(ul)
 | ||||
| //  FORMAT(voc)
 | ||||
| //  FORMAT(vox)
 | ||||
|   FORMAT(wav) | ||||
| //  FORMAT(wve)
 | ||||
| //  FORMAT(xa)
 | ||||
| 
 | ||||
| /*--------------------- Plugin or static format handlers ---------------------*/ | ||||
| 
 | ||||
| #if defined HAVE_ALSA && (defined STATIC_ALSA || !defined HAVE_LIBLTDL) | ||||
|   FORMAT(alsa) | ||||
| #endif | ||||
| #if defined HAVE_AMRNB && (defined STATIC_AMRNB || !defined HAVE_LIBLTDL) | ||||
|   FORMAT(amr_nb) | ||||
| #endif | ||||
| #if defined HAVE_AMRWB && (defined STATIC_AMRWB || !defined HAVE_LIBLTDL) | ||||
|   FORMAT(amr_wb) | ||||
| #endif | ||||
| #if defined HAVE_AO && (defined STATIC_AO || !defined HAVE_LIBLTDL) | ||||
|   FORMAT(ao) | ||||
| #endif | ||||
| #if defined HAVE_COREAUDIO && (defined STATIC_COREAUDIO || !defined HAVE_LIBLTDL) | ||||
|   FORMAT(coreaudio) | ||||
| #endif | ||||
| #if defined HAVE_FLAC && (defined STATIC_FLAC || !defined HAVE_LIBLTDL) | ||||
|   FORMAT(flac) | ||||
| #endif | ||||
| #if defined HAVE_GSM && (defined STATIC_GSM || !defined HAVE_LIBLTDL) | ||||
|   FORMAT(gsm) | ||||
| #endif | ||||
| #if defined HAVE_LPC10 && (defined STATIC_LPC10 || !defined HAVE_LIBLTDL) | ||||
|   FORMAT(lpc10) | ||||
| #endif | ||||
| #if defined HAVE_MP3 && (defined STATIC_MP3 || !defined HAVE_LIBLTDL) | ||||
|   FORMAT(mp3) | ||||
| #endif | ||||
| #if defined HAVE_OPUS && (defined STATIC_OPUS || !defined HAVE_LIBLTDL) | ||||
|   FORMAT(opus) | ||||
| #endif | ||||
| #if defined HAVE_OSS && (defined STATIC_OSS || !defined HAVE_LIBLTDL) | ||||
|   FORMAT(oss) | ||||
| #endif | ||||
| #if defined HAVE_PULSEAUDIO && (defined STATIC_PULSEAUDIO || !defined HAVE_LIBLTDL) | ||||
|   FORMAT(pulseaudio) | ||||
| #endif | ||||
| #if defined HAVE_WAVEAUDIO && (defined STATIC_WAVEAUDIO || !defined HAVE_LIBLTDL) | ||||
|   FORMAT(waveaudio) | ||||
| #endif | ||||
| #if defined HAVE_SNDIO && (defined STATIC_SNDIO || !defined HAVE_LIBLTDL) | ||||
|   FORMAT(sndio) | ||||
| #endif | ||||
| #if defined HAVE_SNDFILE && (defined STATIC_SNDFILE || !defined HAVE_LIBLTDL) | ||||
|   FORMAT(sndfile) | ||||
|   FORMAT(caf) | ||||
|   FORMAT(fap) | ||||
|   FORMAT(mat4) | ||||
|   FORMAT(mat5) | ||||
|   FORMAT(paf) | ||||
|   FORMAT(pvf) | ||||
|   FORMAT(sd2) | ||||
|   FORMAT(w64) | ||||
|   FORMAT(xi) | ||||
| #endif | ||||
| #if defined HAVE_SUNAUDIO && (defined STATIC_SUNAUDIO || !defined HAVE_LIBLTDL) | ||||
|   FORMAT(sunau) | ||||
| #endif | ||||
| #if defined HAVE_OGGVORBIS && (defined STATIC_OGGVORBIS || !defined HAVE_LIBLTDL) | ||||
|   FORMAT(vorbis) | ||||
| #endif | ||||
| #if defined HAVE_WAVPACK && (defined STATIC_WAVPACK || !defined HAVE_LIBLTDL) | ||||
|   FORMAT(wavpack) | ||||
| #endif | ||||
| @ -1,545 +0,0 @@ | ||||
| /* Implements a libSoX internal interface for use in implementing file formats.
 | ||||
|  * All public functions & data are prefixed with lsx_ . | ||||
|  * | ||||
|  * (c) 2005-8 Chris Bagwell and SoX contributors | ||||
|  * | ||||
|  * This library is free software; you can redistribute it and/or modify it | ||||
|  * under the terms of the GNU Lesser General Public License as published by | ||||
|  * the Free Software Foundation; either version 2.1 of the License, or (at | ||||
|  * your option) any later version. | ||||
|  * | ||||
|  * This library is distributed in the hope that it will be useful, but | ||||
|  * WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser | ||||
|  * General Public License for more details. | ||||
|  * | ||||
|  * You should have received a copy of the GNU Lesser General Public License | ||||
|  * along with this library; if not, write to the Free Software Foundation, | ||||
|  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA | ||||
|  */ | ||||
| 
 | ||||
| #include "sox_i.h" | ||||
| #include <string.h> | ||||
| #include <sys/stat.h> | ||||
| #include <stdarg.h> | ||||
| 
 | ||||
| void lsx_fail_errno(sox_format_t * ft, int sox_errno, const char *fmt, ...) | ||||
| { | ||||
|   va_list args; | ||||
| 
 | ||||
|   ft->sox_errno = sox_errno; | ||||
| 
 | ||||
|   va_start(args, fmt); | ||||
| #ifdef HAVE_VSNPRINTF | ||||
|   vsnprintf(ft->sox_errstr, sizeof(ft->sox_errstr), fmt, args); | ||||
| #else | ||||
|   vsprintf(ft->sox_errstr, fmt, args); | ||||
| #endif | ||||
|   va_end(args); | ||||
|   ft->sox_errstr[255] = '\0'; | ||||
| } | ||||
| 
 | ||||
| void lsx_set_signal_defaults(sox_format_t * ft) | ||||
| { | ||||
|   if (!ft->signal.rate     ) ft->signal.rate      = SOX_DEFAULT_RATE; | ||||
|   if (!ft->signal.precision) ft->signal.precision = SOX_DEFAULT_PRECISION; | ||||
|   if (!ft->signal.channels ) ft->signal.channels  = SOX_DEFAULT_CHANNELS; | ||||
| 
 | ||||
|   if (!ft->encoding.bits_per_sample) | ||||
|     ft->encoding.bits_per_sample = ft->signal.precision; | ||||
|   if (ft->encoding.encoding == SOX_ENCODING_UNKNOWN) | ||||
|     ft->encoding.encoding = SOX_ENCODING_SIGN2; | ||||
| } | ||||
| 
 | ||||
| int lsx_check_read_params(sox_format_t * ft, unsigned channels, | ||||
|     sox_rate_t rate, sox_encoding_t encoding, unsigned bits_per_sample, | ||||
|     uint64_t num_samples, sox_bool check_length) | ||||
| { | ||||
|   ft->signal.length = ft->signal.length == SOX_IGNORE_LENGTH? SOX_UNSPEC : num_samples; | ||||
| 
 | ||||
|   if (ft->seekable) | ||||
|     ft->data_start = lsx_tell(ft); | ||||
| 
 | ||||
|   if (channels && ft->signal.channels && ft->signal.channels != channels) | ||||
|     lsx_warn("`%s': overriding number of channels", ft->filename); | ||||
|   else ft->signal.channels = channels; | ||||
| 
 | ||||
|   if (rate && ft->signal.rate && ft->signal.rate != rate) | ||||
|     lsx_warn("`%s': overriding sample rate", ft->filename); | ||||
|   else ft->signal.rate = rate; | ||||
| 
 | ||||
|   if (encoding && ft->encoding.encoding && ft->encoding.encoding != encoding) | ||||
|     lsx_warn("`%s': overriding encoding type", ft->filename); | ||||
|   else ft->encoding.encoding = encoding; | ||||
| 
 | ||||
|   if (bits_per_sample && ft->encoding.bits_per_sample && ft->encoding.bits_per_sample != bits_per_sample) | ||||
|     lsx_warn("`%s': overriding encoding size", ft->filename); | ||||
|   ft->encoding.bits_per_sample = bits_per_sample; | ||||
| 
 | ||||
|   if (check_length && ft->encoding.bits_per_sample && lsx_filelength(ft)) { | ||||
|     uint64_t calculated_length = div_bits(lsx_filelength(ft) - ft->data_start, ft->encoding.bits_per_sample); | ||||
|     if (!ft->signal.length) | ||||
|       ft->signal.length = calculated_length; | ||||
|     else if (num_samples != calculated_length) | ||||
|       lsx_warn("`%s': file header gives the total number of samples as %" PRIu64 " but file length indicates the number is in fact %" PRIu64, ft->filename, num_samples, calculated_length); | ||||
|   } | ||||
| 
 | ||||
|   if (sox_precision(ft->encoding.encoding, ft->encoding.bits_per_sample)) | ||||
|     return SOX_SUCCESS; | ||||
|   lsx_fail_errno(ft, EINVAL, "invalid format for this file type"); | ||||
|   return SOX_EOF; | ||||
| } | ||||
| 
 | ||||
| /* Read in a buffer of data of length len bytes.
 | ||||
|  * Returns number of bytes read. | ||||
|  */ | ||||
| size_t lsx_readbuf(sox_format_t * ft, void *buf, size_t len) | ||||
| { | ||||
|   size_t ret = fread(buf, (size_t) 1, len, (FILE*)ft->fp); | ||||
|   if (ret != len && ferror((FILE*)ft->fp)) | ||||
|     lsx_fail_errno(ft, errno, "lsx_readbuf"); | ||||
|   ft->tell_off += ret; | ||||
|   return ret; | ||||
| } | ||||
| 
 | ||||
| /* Skip input without seeking. */ | ||||
| int lsx_skipbytes(sox_format_t * ft, size_t n) | ||||
| { | ||||
|   unsigned char trash; | ||||
| 
 | ||||
|   while (n--) | ||||
|     if (lsx_readb(ft, &trash) == SOX_EOF) | ||||
|       return (SOX_EOF); | ||||
| 
 | ||||
|   return (SOX_SUCCESS); | ||||
| } | ||||
| 
 | ||||
| /* Pad output. */ | ||||
| int lsx_padbytes(sox_format_t * ft, size_t n) | ||||
| { | ||||
|   while (n--) | ||||
|     if (lsx_writeb(ft, '\0') == SOX_EOF) | ||||
|       return (SOX_EOF); | ||||
| 
 | ||||
|   return (SOX_SUCCESS); | ||||
| } | ||||
| 
 | ||||
| /* Write a buffer of data of length bytes.
 | ||||
|  * Returns number of bytes written. | ||||
|  */ | ||||
| size_t lsx_writebuf(sox_format_t * ft, void const * buf, size_t len) | ||||
| { | ||||
|   size_t ret = fwrite(buf, (size_t) 1, len, (FILE*)ft->fp); | ||||
|   if (ret != len) { | ||||
|     lsx_fail_errno(ft, errno, "error writing output file"); | ||||
|     clearerr((FILE*)ft->fp); /* Allows us to seek back to write header */ | ||||
|   } | ||||
|   ft->tell_off += ret; | ||||
|   return ret; | ||||
| } | ||||
| 
 | ||||
| sox_uint64_t lsx_filelength(sox_format_t * ft) | ||||
| { | ||||
|   struct stat st; | ||||
|   int ret = ft->fp ? fstat(fileno((FILE*)ft->fp), &st) : 0; | ||||
| 
 | ||||
|   return (!ret && (st.st_mode & S_IFREG))? (uint64_t)st.st_size : 0; | ||||
| } | ||||
| 
 | ||||
| int lsx_flush(sox_format_t * ft) | ||||
| { | ||||
|   return fflush((FILE*)ft->fp); | ||||
| } | ||||
| 
 | ||||
| off_t lsx_tell(sox_format_t * ft) | ||||
| { | ||||
|   return ft->seekable? (off_t)ftello((FILE*)ft->fp) : (off_t)ft->tell_off; | ||||
| } | ||||
| 
 | ||||
| int lsx_eof(sox_format_t * ft) | ||||
| { | ||||
|   return feof((FILE*)ft->fp); | ||||
| } | ||||
| 
 | ||||
| int lsx_error(sox_format_t * ft) | ||||
| { | ||||
|   return ferror((FILE*)ft->fp); | ||||
| } | ||||
| 
 | ||||
| void lsx_rewind(sox_format_t * ft) | ||||
| { | ||||
|   rewind((FILE*)ft->fp); | ||||
|   ft->tell_off = 0; | ||||
| } | ||||
| 
 | ||||
| void lsx_clearerr(sox_format_t * ft) | ||||
| { | ||||
|   clearerr((FILE*)ft->fp); | ||||
|   ft->sox_errno = 0; | ||||
| } | ||||
| 
 | ||||
| int lsx_unreadb(sox_format_t * ft, unsigned b) | ||||
| { | ||||
|   return ungetc((int)b, ft->fp); | ||||
| } | ||||
| 
 | ||||
| /* Implements traditional fseek() behavior.  Meant to abstract out
 | ||||
|  * file operations so that they could one day also work on memory | ||||
|  * buffers. | ||||
|  * | ||||
|  * N.B. Can only seek forwards on non-seekable streams! | ||||
|  */ | ||||
| int lsx_seeki(sox_format_t * ft, off_t offset, int whence) | ||||
| { | ||||
|     if (ft->seekable == 0) { | ||||
|         /* If a stream peel off chars else EPERM */ | ||||
|         if (whence == SEEK_CUR) { | ||||
|             while (offset > 0 && !feof((FILE*)ft->fp)) { | ||||
|                 getc((FILE*)ft->fp); | ||||
|                 offset--; | ||||
|                 ++ft->tell_off; | ||||
|             } | ||||
|             if (offset) | ||||
|                 lsx_fail_errno(ft,SOX_EOF, "offset past EOF"); | ||||
|             else | ||||
|                 ft->sox_errno = SOX_SUCCESS; | ||||
|         } else | ||||
|             lsx_fail_errno(ft,SOX_EPERM, "file not seekable"); | ||||
|     } else { | ||||
|         if (fseeko((FILE*)ft->fp, offset, whence) == -1) | ||||
|             lsx_fail_errno(ft,errno, "%s", strerror(errno)); | ||||
|         else | ||||
|             ft->sox_errno = SOX_SUCCESS; | ||||
|     } | ||||
|     return ft->sox_errno; | ||||
| } | ||||
| 
 | ||||
| int lsx_offset_seek(sox_format_t * ft, off_t byte_offset, off_t to_sample) | ||||
| { | ||||
|   double wide_sample = to_sample - (to_sample % ft->signal.channels); | ||||
|   double to_d = wide_sample * ft->encoding.bits_per_sample / 8; | ||||
|   off_t to = to_d; | ||||
|   return (to != to_d)? SOX_EOF : lsx_seeki(ft, (byte_offset + to), SEEK_SET); | ||||
| } | ||||
| 
 | ||||
| /* Read and write known datatypes in "machine format".  Swap if indicated.
 | ||||
|  * They all return SOX_EOF on error and SOX_SUCCESS on success. | ||||
|  */ | ||||
| /* Read n-char string (and possibly null-terminating).
 | ||||
|  * Stop reading and null-terminate string if either a 0 or \n is reached. | ||||
|  */ | ||||
| int lsx_reads(sox_format_t * ft, char *c, size_t len) | ||||
| { | ||||
|     char *sc; | ||||
|     char in; | ||||
| 
 | ||||
|     sc = c; | ||||
|     do | ||||
|     { | ||||
|         if (lsx_readbuf(ft, &in, (size_t)1) != 1) | ||||
|         { | ||||
|             *sc = 0; | ||||
|             return (SOX_EOF); | ||||
|         } | ||||
|         if (in == 0 || in == '\n') | ||||
|             break; | ||||
| 
 | ||||
|         *sc = in; | ||||
|         sc++; | ||||
|     } while (sc - c < (ptrdiff_t)len); | ||||
|     *sc = 0; | ||||
|     return(SOX_SUCCESS); | ||||
| } | ||||
| 
 | ||||
| /* Write null-terminated string (without \0). */ | ||||
| int lsx_writes(sox_format_t * ft, char const * c) | ||||
| { | ||||
|         if (lsx_writebuf(ft, c, strlen(c)) != strlen(c)) | ||||
|                 return(SOX_EOF); | ||||
|         return(SOX_SUCCESS); | ||||
| } | ||||
| 
 | ||||
| /* return swapped 32-bit float */ | ||||
| static void lsx_swapf(float * f) | ||||
| { | ||||
|     union { | ||||
|         uint32_t dw; | ||||
|         float f; | ||||
|     } u; | ||||
| 
 | ||||
|     u.f= *f; | ||||
|     u.dw= (u.dw>>24) | ((u.dw>>8)&0xff00) | ((u.dw<<8)&0xff0000) | (u.dw<<24); | ||||
|     *f = u.f; | ||||
| } | ||||
| 
 | ||||
| static void swap(void * data, size_t len) | ||||
| { | ||||
|   uint8_t * bytes = (uint8_t *)data; | ||||
|   size_t i; | ||||
| 
 | ||||
|   for (i = 0; i < len / 2; ++i) { | ||||
|     char tmp = bytes[i]; | ||||
|     bytes[i] = bytes[len - 1 - i]; | ||||
|     bytes[len - 1 - i] = tmp; | ||||
|   } | ||||
| } | ||||
| 
 | ||||
| static double lsx_swapdf(double data) | ||||
| { | ||||
|   swap(&data, sizeof(data)); | ||||
|   return data; | ||||
| } | ||||
| 
 | ||||
| static uint64_t lsx_swapqw(uint64_t data) | ||||
| { | ||||
|   swap(&data, sizeof(data)); | ||||
|   return data; | ||||
| } | ||||
| 
 | ||||
| /* Lookup table to reverse the bit order of a byte. ie MSB become LSB */ | ||||
| static uint8_t const cswap[256] = { | ||||
|   0x00, 0x80, 0x40, 0xC0, 0x20, 0xA0, 0x60, 0xE0, 0x10, 0x90, 0x50, 0xD0, | ||||
|   0x30, 0xB0, 0x70, 0xF0, 0x08, 0x88, 0x48, 0xC8, 0x28, 0xA8, 0x68, 0xE8, | ||||
|   0x18, 0x98, 0x58, 0xD8, 0x38, 0xB8, 0x78, 0xF8, 0x04, 0x84, 0x44, 0xC4, | ||||
|   0x24, 0xA4, 0x64, 0xE4, 0x14, 0x94, 0x54, 0xD4, 0x34, 0xB4, 0x74, 0xF4, | ||||
|   0x0C, 0x8C, 0x4C, 0xCC, 0x2C, 0xAC, 0x6C, 0xEC, 0x1C, 0x9C, 0x5C, 0xDC, | ||||
|   0x3C, 0xBC, 0x7C, 0xFC, 0x02, 0x82, 0x42, 0xC2, 0x22, 0xA2, 0x62, 0xE2, | ||||
|   0x12, 0x92, 0x52, 0xD2, 0x32, 0xB2, 0x72, 0xF2, 0x0A, 0x8A, 0x4A, 0xCA, | ||||
|   0x2A, 0xAA, 0x6A, 0xEA, 0x1A, 0x9A, 0x5A, 0xDA, 0x3A, 0xBA, 0x7A, 0xFA, | ||||
|   0x06, 0x86, 0x46, 0xC6, 0x26, 0xA6, 0x66, 0xE6, 0x16, 0x96, 0x56, 0xD6, | ||||
|   0x36, 0xB6, 0x76, 0xF6, 0x0E, 0x8E, 0x4E, 0xCE, 0x2E, 0xAE, 0x6E, 0xEE, | ||||
|   0x1E, 0x9E, 0x5E, 0xDE, 0x3E, 0xBE, 0x7E, 0xFE, 0x01, 0x81, 0x41, 0xC1, | ||||
|   0x21, 0xA1, 0x61, 0xE1, 0x11, 0x91, 0x51, 0xD1, 0x31, 0xB1, 0x71, 0xF1, | ||||
|   0x09, 0x89, 0x49, 0xC9, 0x29, 0xA9, 0x69, 0xE9, 0x19, 0x99, 0x59, 0xD9, | ||||
|   0x39, 0xB9, 0x79, 0xF9, 0x05, 0x85, 0x45, 0xC5, 0x25, 0xA5, 0x65, 0xE5, | ||||
|   0x15, 0x95, 0x55, 0xD5, 0x35, 0xB5, 0x75, 0xF5, 0x0D, 0x8D, 0x4D, 0xCD, | ||||
|   0x2D, 0xAD, 0x6D, 0xED, 0x1D, 0x9D, 0x5D, 0xDD, 0x3D, 0xBD, 0x7D, 0xFD, | ||||
|   0x03, 0x83, 0x43, 0xC3, 0x23, 0xA3, 0x63, 0xE3, 0x13, 0x93, 0x53, 0xD3, | ||||
|   0x33, 0xB3, 0x73, 0xF3, 0x0B, 0x8B, 0x4B, 0xCB, 0x2B, 0xAB, 0x6B, 0xEB, | ||||
|   0x1B, 0x9B, 0x5B, 0xDB, 0x3B, 0xBB, 0x7B, 0xFB, 0x07, 0x87, 0x47, 0xC7, | ||||
|   0x27, 0xA7, 0x67, 0xE7, 0x17, 0x97, 0x57, 0xD7, 0x37, 0xB7, 0x77, 0xF7, | ||||
|   0x0F, 0x8F, 0x4F, 0xCF, 0x2F, 0xAF, 0x6F, 0xEF, 0x1F, 0x9F, 0x5F, 0xDF, | ||||
|   0x3F, 0xBF, 0x7F, 0xFF | ||||
| }; | ||||
| 
 | ||||
| /* Utilities to byte-swap values, use libc optimized macros if possible  */ | ||||
| #define TWIDDLE_BYTE(ub, type) \ | ||||
|   do { \
 | ||||
|     if (ft->encoding.reverse_bits) \
 | ||||
|       ub = cswap[ub]; \
 | ||||
|     if (ft->encoding.reverse_nibbles) \
 | ||||
|       ub = ((ub & 15) << 4) | (ub >> 4); \
 | ||||
|   } while (0); | ||||
| 
 | ||||
| #define TWIDDLE_WORD(uw, type) \ | ||||
|   if (ft->encoding.reverse_bytes) \
 | ||||
|     uw = lsx_swap ## type(uw); | ||||
| 
 | ||||
| #define TWIDDLE_FLOAT(f, type) \ | ||||
|   if (ft->encoding.reverse_bytes) \
 | ||||
|     lsx_swapf(&f); | ||||
| 
 | ||||
| /* N.B. This macro doesn't work for unaligned types (e.g. 3-byte
 | ||||
|    types). */ | ||||
| #define READ_FUNC(type, size, ctype, twiddle) \ | ||||
|   size_t lsx_read_ ## type ## _buf( \
 | ||||
|       sox_format_t * ft, ctype *buf, size_t len) \
 | ||||
|   { \
 | ||||
|     size_t n, nread; \
 | ||||
|     nread = lsx_readbuf(ft, buf, len * size) / size; \
 | ||||
|     for (n = 0; n < nread; n++) \
 | ||||
|       twiddle(buf[n], type); \
 | ||||
|     return nread; \
 | ||||
|   } | ||||
| 
 | ||||
| /* Unpack a 3-byte value from a uint8_t * */ | ||||
| #define sox_unpack3(p) (ft->encoding.reverse_bytes == MACHINE_IS_BIGENDIAN? \ | ||||
|   ((p)[0] | ((p)[1] << 8) | ((p)[2] << 16)) : \
 | ||||
|   ((p)[2] | ((p)[1] << 8) | ((p)[0] << 16))) | ||||
| 
 | ||||
| /* This (slower) macro works for unaligned types (e.g. 3-byte types)
 | ||||
|    that need to be unpacked. */ | ||||
| #define READ_FUNC_UNPACK(type, size, ctype, twiddle) \ | ||||
|   size_t lsx_read_ ## type ## _buf( \
 | ||||
|       sox_format_t * ft, ctype *buf, size_t len) \
 | ||||
|   { \
 | ||||
|     size_t n, nread; \
 | ||||
|     uint8_t *data = lsx_malloc(size * len); \
 | ||||
|     nread = lsx_readbuf(ft, data, len * size) / size; \
 | ||||
|     for (n = 0; n < nread; n++) \
 | ||||
|       buf[n] = sox_unpack ## size(data + n * size); \
 | ||||
|     free(data); \
 | ||||
|     return n; \
 | ||||
|   } | ||||
| 
 | ||||
| READ_FUNC(b, 1, uint8_t, TWIDDLE_BYTE) | ||||
| READ_FUNC(w, 2, uint16_t, TWIDDLE_WORD) | ||||
| READ_FUNC_UNPACK(3, 3, sox_uint24_t, TWIDDLE_WORD) | ||||
| READ_FUNC(dw, 4, uint32_t, TWIDDLE_WORD) | ||||
| READ_FUNC(qw, 8, uint64_t, TWIDDLE_WORD) | ||||
| READ_FUNC(f, sizeof(float), float, TWIDDLE_FLOAT) | ||||
| READ_FUNC(df, sizeof(double), double, TWIDDLE_WORD) | ||||
| 
 | ||||
| #define READ1_FUNC(type, ctype) \ | ||||
| int lsx_read ## type(sox_format_t * ft, ctype * datum) { \
 | ||||
|   if (lsx_read_ ## type ## _buf(ft, datum, (size_t)1) == 1) \
 | ||||
|     return SOX_SUCCESS; \
 | ||||
|   if (!lsx_error(ft)) \
 | ||||
|     lsx_fail_errno(ft, errno, premature_eof); \
 | ||||
|   return SOX_EOF; \
 | ||||
| } | ||||
| 
 | ||||
| static char const premature_eof[] = "premature EOF"; | ||||
| 
 | ||||
| READ1_FUNC(b,  uint8_t) | ||||
| READ1_FUNC(w,  uint16_t) | ||||
| READ1_FUNC(3,  sox_uint24_t) | ||||
| READ1_FUNC(dw, uint32_t) | ||||
| READ1_FUNC(qw, uint64_t) | ||||
| READ1_FUNC(f,  float) | ||||
| READ1_FUNC(df, double) | ||||
| 
 | ||||
| int lsx_readchars(sox_format_t * ft, char * chars, size_t len) | ||||
| { | ||||
|   size_t ret = lsx_readbuf(ft, chars, len); | ||||
|   if (ret == len) | ||||
|     return SOX_SUCCESS; | ||||
|   if (!lsx_error(ft)) | ||||
|     lsx_fail_errno(ft, errno, premature_eof); | ||||
|   return SOX_EOF; | ||||
| } | ||||
| 
 | ||||
| int lsx_read_fields(sox_format_t *ft, uint32_t *len,  const char *spec, ...) | ||||
| { | ||||
|     int err = SOX_SUCCESS; | ||||
|     va_list ap; | ||||
| 
 | ||||
| #define do_read(type, f, n) do {                                \ | ||||
|         size_t nr;                                              \
 | ||||
|         if (*len < n * sizeof(type)) {                          \
 | ||||
|             err = SOX_EOF;                                      \
 | ||||
|             goto end;                                           \
 | ||||
|         }                                                       \
 | ||||
|         nr = lsx_read_##f##_buf(ft, va_arg(ap, type *), r);     \
 | ||||
|         if (nr != n)                                            \
 | ||||
|             err = SOX_EOF;                                      \
 | ||||
|         *len -= nr * sizeof(type);                              \
 | ||||
|     } while (0) | ||||
| 
 | ||||
|     va_start(ap, spec); | ||||
| 
 | ||||
|     while (*spec) { | ||||
|         unsigned long r = 1; | ||||
|         char c = *spec; | ||||
| 
 | ||||
|         if (c >= '0' && c <= '9') { | ||||
|             char *next; | ||||
|             r = strtoul(spec, &next, 10); | ||||
|             spec = next; | ||||
|             c = *spec; | ||||
|         } else if (c == '*') { | ||||
|             r = va_arg(ap, int); | ||||
|             c = *++spec; | ||||
|         } | ||||
| 
 | ||||
|         switch (c) { | ||||
|         case 'b': do_read(uint8_t, b, r);       break; | ||||
|         case 'h': do_read(uint16_t, w, r);      break; | ||||
|         case 'i': do_read(uint32_t, dw, r);     break; | ||||
|         case 'q': do_read(uint64_t, qw, r);     break; | ||||
|         case 'x': err = lsx_skipbytes(ft, r);   break; | ||||
| 
 | ||||
|         default: | ||||
|             lsx_fail("lsx_read_fields: invalid format character '%c'", c); | ||||
|             err = SOX_EOF; | ||||
|             break; | ||||
|         } | ||||
| 
 | ||||
|         if (err) | ||||
|             break; | ||||
| 
 | ||||
|         spec++; | ||||
|     } | ||||
| 
 | ||||
| end: | ||||
|     va_end(ap); | ||||
| 
 | ||||
| #undef do_read | ||||
| 
 | ||||
|     return err; | ||||
| } | ||||
| 
 | ||||
| /* N.B. This macro doesn't work for unaligned types (e.g. 3-byte
 | ||||
|    types). */ | ||||
| #define WRITE_FUNC(type, size, ctype, twiddle) \ | ||||
|   size_t lsx_write_ ## type ## _buf( \
 | ||||
|       sox_format_t * ft, ctype *buf, size_t len) \
 | ||||
|   { \
 | ||||
|     size_t n, nwritten; \
 | ||||
|     for (n = 0; n < len; n++) \
 | ||||
|       twiddle(buf[n], type); \
 | ||||
|     nwritten = lsx_writebuf(ft, buf, len * size); \
 | ||||
|     return nwritten / size; \
 | ||||
|   } | ||||
| 
 | ||||
| /* Pack a 3-byte value to a uint8_t * */ | ||||
| #define sox_pack3(p, v) do {if (ft->encoding.reverse_bytes == MACHINE_IS_BIGENDIAN)\ | ||||
| {(p)[0] = v & 0xff; (p)[1] = (v >> 8) & 0xff; (p)[2] = (v >> 16) & 0xff;} else \
 | ||||
| {(p)[2] = v & 0xff; (p)[1] = (v >> 8) & 0xff; (p)[0] = (v >> 16) & 0xff;} \
 | ||||
| } while (0) | ||||
| 
 | ||||
| /* This (slower) macro works for unaligned types (e.g. 3-byte types)
 | ||||
|    that need to be packed. */ | ||||
| #define WRITE_FUNC_PACK(type, size, ctype, twiddle) \ | ||||
|   size_t lsx_write_ ## type ## _buf( \
 | ||||
|       sox_format_t * ft, ctype *buf, size_t len) \
 | ||||
|   { \
 | ||||
|     size_t n, nwritten; \
 | ||||
|     uint8_t *data = lsx_malloc(size * len); \
 | ||||
|     for (n = 0; n < len; n++) \
 | ||||
|       sox_pack ## size(data + n * size, buf[n]); \
 | ||||
|     nwritten = lsx_writebuf(ft, data, len * size); \
 | ||||
|     free(data); \
 | ||||
|     return nwritten / size; \
 | ||||
|   } | ||||
| 
 | ||||
| WRITE_FUNC(b, 1, uint8_t, TWIDDLE_BYTE) | ||||
| WRITE_FUNC(w, 2, uint16_t, TWIDDLE_WORD) | ||||
| WRITE_FUNC_PACK(3, 3, sox_uint24_t, TWIDDLE_WORD) | ||||
| WRITE_FUNC(dw, 4, uint32_t, TWIDDLE_WORD) | ||||
| WRITE_FUNC(qw, 8, uint64_t, TWIDDLE_WORD) | ||||
| WRITE_FUNC(f, sizeof(float), float, TWIDDLE_FLOAT) | ||||
| WRITE_FUNC(df, sizeof(double), double, TWIDDLE_WORD) | ||||
| 
 | ||||
| #define WRITE1U_FUNC(type, ctype) \ | ||||
|   int lsx_write ## type(sox_format_t * ft, unsigned d) \
 | ||||
|   { ctype datum = (ctype)d; \
 | ||||
|     return lsx_write_ ## type ## _buf(ft, &datum, (size_t)1) == 1 ? SOX_SUCCESS : SOX_EOF; \
 | ||||
|   } | ||||
| 
 | ||||
| #define WRITE1S_FUNC(type, ctype) \ | ||||
|   int lsx_writes ## type(sox_format_t * ft, signed d) \
 | ||||
|   { ctype datum = (ctype)d; \
 | ||||
|     return lsx_write_ ## type ## _buf(ft, &datum, (size_t)1) == 1 ? SOX_SUCCESS : SOX_EOF; \
 | ||||
|   } | ||||
| 
 | ||||
| #define WRITE1_FUNC(type, ctype) \ | ||||
|   int lsx_write ## type(sox_format_t * ft, ctype datum) \
 | ||||
|   { \
 | ||||
|     return lsx_write_ ## type ## _buf(ft, &datum, (size_t)1) == 1 ? SOX_SUCCESS : SOX_EOF; \
 | ||||
|   } | ||||
| 
 | ||||
| WRITE1U_FUNC(b, uint8_t) | ||||
| WRITE1U_FUNC(w, uint16_t) | ||||
| WRITE1U_FUNC(3, sox_uint24_t) | ||||
| WRITE1U_FUNC(dw, uint32_t) | ||||
| WRITE1_FUNC(qw, uint64_t) | ||||
| WRITE1S_FUNC(b, uint8_t) | ||||
| WRITE1S_FUNC(w, uint16_t) | ||||
| WRITE1_FUNC(df, double) | ||||
| 
 | ||||
| int lsx_writef(sox_format_t * ft, double datum) | ||||
| { | ||||
|   float f = datum; | ||||
|   return lsx_write_f_buf(ft, &f, (size_t) 1) == 1 ? SOX_SUCCESS : SOX_EOF; | ||||
| } | ||||
									
										
											File diff suppressed because it is too large
											Load Diff
										
									
								
							
						| @ -1,21 +0,0 @@ | ||||
| /* libSoX G711.h - include for G711 u-law and a-law conversion routines
 | ||||
|  * | ||||
|  * Copyright (C) 2001 Chris Bagwell | ||||
|  * | ||||
|  * Permission to use, copy, modify, and distribute this software and its | ||||
|  * documentation for any purpose and without fee is hereby granted, provided | ||||
|  * that the above copyright notice appear in all copies and that both that | ||||
|  * copyright notice and this permission notice appear in supporting | ||||
|  * documentation.  This software is provided "as is" without express or | ||||
|  * implied warranty. | ||||
|  */ | ||||
| 
 | ||||
| extern const uint8_t lsx_13linear2alaw[0x2000]; | ||||
| extern const int16_t lsx_alaw2linear16[256]; | ||||
| #define sox_13linear2alaw(sw) (lsx_13linear2alaw[((sw) + 0x1000)]) | ||||
| #define sox_alaw2linear16(uc) (lsx_alaw2linear16[uc]) | ||||
| 
 | ||||
| extern const uint8_t lsx_14linear2ulaw[0x4000]; | ||||
| extern const int16_t lsx_ulaw2linear16[256]; | ||||
| #define sox_14linear2ulaw(sw) (lsx_14linear2ulaw[((sw) + 0x2000)]) | ||||
| #define sox_ulaw2linear16(uc) (lsx_ulaw2linear16[uc]) | ||||
| @ -1,349 +0,0 @@ | ||||
| /* lsx_getopt for SoX
 | ||||
|  * | ||||
|  * (c) 2011 Doug Cook and SoX contributors | ||||
|  * | ||||
|  * This library is free software; you can redistribute it and/or modify it | ||||
|  * under the terms of the GNU Lesser General Public License as published by | ||||
|  * the Free Software Foundation; either version 2.1 of the License, or (at | ||||
|  * your option) any later version. | ||||
|  * | ||||
|  * This library is distributed in the hope that it will be useful, but | ||||
|  * WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser | ||||
|  * General Public License for more details. | ||||
|  * | ||||
|  * You should have received a copy of the GNU Lesser General Public License | ||||
|  * along with this library; if not, write to the Free Software Foundation, | ||||
|  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA | ||||
|  */ | ||||
| 
 | ||||
| #include "sox.h" | ||||
| #include <assert.h> | ||||
| #include <stdlib.h> | ||||
| #include <string.h> | ||||
| 
 | ||||
| void | ||||
| lsx_getopt_init( | ||||
|     LSX_PARAM_IN             int argc,                      /* Number of arguments in argv */ | ||||
|     LSX_PARAM_IN_COUNT(argc) char * const * argv,           /* Array of arguments */ | ||||
|     LSX_PARAM_IN_Z           char const * shortopts,        /* Short option characters */ | ||||
|     LSX_PARAM_IN_OPT         lsx_option_t const * longopts, /* Array of long option descriptors */ | ||||
|     LSX_PARAM_IN             lsx_getopt_flags_t flags,      /* Flags for longonly and opterr */ | ||||
|     LSX_PARAM_IN             int first,                     /* First argument to check (usually 1) */ | ||||
|     LSX_PARAM_OUT            lsx_getopt_t * state)          /* State object to initialize */ | ||||
| { | ||||
|     assert(argc >= 0); | ||||
|     assert(argv != NULL); | ||||
|     assert(shortopts); | ||||
|     assert(first >= 0); | ||||
|     assert(first <= argc); | ||||
|     assert(state); | ||||
|     if (state) | ||||
|     { | ||||
|         if (argc < 0 || | ||||
|             !argv || | ||||
|             !shortopts || | ||||
|             first < 0 || | ||||
|             first > argc) | ||||
|         { | ||||
|             memset(state, 0, sizeof(*state)); | ||||
|         } | ||||
|         else | ||||
|         { | ||||
|             state->argc = argc; | ||||
|             state->argv = argv; | ||||
|             state->shortopts = | ||||
|                 (shortopts[0] == '+' || shortopts[0] == '-') /* Requesting GNU special behavior? */ | ||||
|                 ? shortopts + 1 /* Ignore request. */ | ||||
|                 : shortopts; /* No special behavior requested. */ | ||||
|             state->longopts = longopts; | ||||
|             state->flags = flags; | ||||
|             state->curpos = NULL; | ||||
|             state->ind = first; | ||||
|             state->opt = '?'; | ||||
|             state->arg = NULL; | ||||
|             state->lngind = -1; | ||||
|         } | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| static void CheckCurPosEnd( | ||||
|     LSX_PARAM_INOUT lsx_getopt_t * state) | ||||
| { | ||||
|     if (!state->curpos[0]) | ||||
|     { | ||||
|         state->curpos = NULL; | ||||
|         state->ind++; | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| int | ||||
| lsx_getopt( | ||||
|     LSX_PARAM_INOUT lsx_getopt_t * state) | ||||
| { | ||||
|     int oerr; | ||||
|     assert(state); | ||||
|     if (!state) | ||||
|     { | ||||
|         lsx_fail("lsx_getopt called with state=NULL"); | ||||
|         return -1; | ||||
|     } | ||||
| 
 | ||||
|     assert(state->argc >= 0); | ||||
|     assert(state->argv != NULL); | ||||
|     assert(state->shortopts); | ||||
|     assert(state->ind >= 0); | ||||
|     assert(state->ind <= state->argc + 1); | ||||
| 
 | ||||
|     oerr = 0 != (state->flags & lsx_getopt_flag_opterr); | ||||
|     state->opt = 0; | ||||
|     state->arg = NULL; | ||||
|     state->lngind = -1; | ||||
| 
 | ||||
|     if (state->argc < 0 || | ||||
|         !state->argv || | ||||
|         !state->shortopts || | ||||
|         state->ind < 0) | ||||
|     { /* programmer error */ | ||||
|         lsx_fail("lsx_getopt called with invalid information"); | ||||
|         state->curpos = NULL; | ||||
|         return -1; | ||||
|     } | ||||
|     else if ( | ||||
|         state->argc <= state->ind || | ||||
|         !state->argv[state->ind] || | ||||
|         state->argv[state->ind][0] != '-' || | ||||
|         state->argv[state->ind][1] == '\0') | ||||
|     { /* return no more options */ | ||||
|         state->curpos = NULL; | ||||
|         return -1; | ||||
|     } | ||||
|     else if (state->argv[state->ind][1] == '-' && state->argv[state->ind][2] == '\0') | ||||
|     { /* skip "--", return no more options. */ | ||||
|         state->curpos = NULL; | ||||
|         state->ind++; | ||||
|         return -1; | ||||
|     } | ||||
|     else | ||||
|     { /* Look for the next option */ | ||||
|         char const * current = state->argv[state->ind]; | ||||
|         char const * param = current + 1; | ||||
| 
 | ||||
|         if (state->curpos == NULL || | ||||
|             state->curpos <= param || | ||||
|             param + strlen(param) <= state->curpos) | ||||
|         { /* Start parsing a new parameter - check for a long option */ | ||||
|             state->curpos = NULL; | ||||
| 
 | ||||
|             if (state->longopts && | ||||
|                 (param[0] == '-' || (state->flags & lsx_getopt_flag_longonly))) | ||||
|             { | ||||
|                 size_t nameLen; | ||||
|                 int doubleDash = param[0] == '-'; | ||||
|                 if (doubleDash) | ||||
|                 { | ||||
|                     param++; | ||||
|                 } | ||||
| 
 | ||||
|                 for (nameLen = 0; param[nameLen] && param[nameLen] != '='; nameLen++) | ||||
|                 {} | ||||
| 
 | ||||
|                 /* For single-dash, you have to specify at least two letters in the name. */ | ||||
|                 if (doubleDash || nameLen >= 2) | ||||
|                 { | ||||
|                     lsx_option_t const * pCur; | ||||
|                     lsx_option_t const * pMatch = NULL; | ||||
|                     int matches = 0; | ||||
| 
 | ||||
|                     for (pCur = state->longopts; pCur->name; pCur++) | ||||
|                     { | ||||
|                         if (0 == strncmp(pCur->name, param, nameLen)) | ||||
|                         { /* Prefix match. */ | ||||
|                             matches++; | ||||
|                             pMatch = pCur; | ||||
|                             if (nameLen == strlen(pCur->name)) | ||||
|                             { /* Exact match - no ambiguity, stop search. */ | ||||
|                                 matches = 1; | ||||
|                                 break; | ||||
|                             } | ||||
|                         } | ||||
|                     } | ||||
| 
 | ||||
|                     if (matches == 1) | ||||
|                     { /* Matched. */ | ||||
|                         state->ind++; | ||||
| 
 | ||||
|                         if (param[nameLen]) | ||||
|                         { /* --name=value */ | ||||
|                             if (pMatch->has_arg) | ||||
|                             { /* Required or optional arg - done. */ | ||||
|                                 state->arg = param + nameLen + 1; | ||||
|                             } | ||||
|                             else | ||||
|                             { /* No arg expected. */ | ||||
|                                 if (oerr) | ||||
|                                 { | ||||
|                                     lsx_warn("`%s' did not expect an argument from `%s'", | ||||
|                                         pMatch->name, | ||||
|                                         current); | ||||
|                                 } | ||||
|                                 return '?'; | ||||
|                             } | ||||
|                         } | ||||
|                         else if (pMatch->has_arg == lsx_option_arg_required) | ||||
|                         { /* Arg required. */ | ||||
|                             state->arg = state->argv[state->ind]; | ||||
|                             state->ind++; | ||||
|                             if (state->ind > state->argc) | ||||
|                             { | ||||
|                                 if (oerr) | ||||
|                                 { | ||||
|                                     lsx_warn("`%s' requires an argument from `%s'", | ||||
|                                         pMatch->name, | ||||
|                                         current); | ||||
|                                 } | ||||
|                                 return state->shortopts[0] == ':' ? ':' : '?'; /* Missing required value. */ | ||||
|                             } | ||||
|                         } | ||||
| 
 | ||||
|                         state->lngind = pMatch - state->longopts; | ||||
|                         if (pMatch->flag) | ||||
|                         { | ||||
|                             *pMatch->flag = pMatch->val; | ||||
|                             return 0; | ||||
|                         } | ||||
|                         else | ||||
|                         { | ||||
|                             return pMatch->val; | ||||
|                         } | ||||
|                     } | ||||
|                     else if (matches == 0 && doubleDash) | ||||
|                     { /* No match */ | ||||
|                         if (oerr) | ||||
|                         { | ||||
|                             lsx_warn("parameter not recognized from `%s'", current); | ||||
|                         } | ||||
|                         state->ind++; | ||||
|                         return '?'; | ||||
|                     } | ||||
|                     else if (matches > 1) | ||||
|                     { /* Ambiguous. */ | ||||
|                         if (oerr) | ||||
|                         { | ||||
|                             lsx_warn("parameter `%s' is ambiguous:", current); | ||||
|                             for (pCur = state->longopts; pCur->name; pCur++) | ||||
|                             { | ||||
|                                 if (0 == strncmp(pCur->name, param, nameLen)) | ||||
|                                 { | ||||
|                                     lsx_warn("parameter `%s' could be `--%s'", current, pCur->name); | ||||
|                                 } | ||||
|                             } | ||||
|                         } | ||||
|                         state->ind++; | ||||
|                         return '?'; | ||||
|                     } | ||||
|                 } | ||||
|             } | ||||
| 
 | ||||
|             state->curpos = param; | ||||
|         } | ||||
| 
 | ||||
|         state->opt = state->curpos[0]; | ||||
|         if (state->opt == ':') | ||||
|         { /* ':' is never a valid short option character */ | ||||
|             if (oerr) | ||||
|             { | ||||
|                 lsx_warn("option `%c' not recognized", state->opt); | ||||
|             } | ||||
|             state->curpos++; | ||||
|             CheckCurPosEnd(state); | ||||
|             return '?'; /* unrecognized option */ | ||||
|         } | ||||
|         else | ||||
|         { /* Short option needs to be matched from option list */ | ||||
|             char const * pShortopt = strchr(state->shortopts, state->opt); | ||||
|             state->curpos++; | ||||
| 
 | ||||
|             if (!pShortopt) | ||||
|             { /* unrecognized option */ | ||||
|                 if (oerr) | ||||
|                 { | ||||
|                     lsx_warn("option `%c' not recognized", state->opt); | ||||
|                 } | ||||
|                 CheckCurPosEnd(state); | ||||
|                 return '?'; | ||||
|             } | ||||
|             else if (pShortopt[1] == ':' && state->curpos[0]) | ||||
|             { /* Return the rest of the parameter as the option's value */ | ||||
|                 state->arg = state->curpos; | ||||
|                 state->curpos = NULL; | ||||
|                 state->ind++; | ||||
|                 return state->opt; | ||||
|             } | ||||
|             else if (pShortopt[1] == ':' && pShortopt[2] != ':') | ||||
|             { /* Option requires a value */ | ||||
|                 state->curpos = NULL; | ||||
|                 state->ind++; | ||||
|                 state->arg = state->argv[state->ind]; | ||||
|                 state->ind++; | ||||
|                 if (state->ind <= state->argc) | ||||
|                 { /* A value was present, so we're good. */ | ||||
|                     return state->opt; | ||||
|                 } | ||||
|                 else | ||||
|                 {  /* Missing required value. */ | ||||
|                     if (oerr) | ||||
|                     { | ||||
|                         lsx_warn("option `%c' requires an argument", | ||||
|                             state->opt); | ||||
|                     } | ||||
|                     return state->shortopts[0] == ':' ? ':' : '?'; | ||||
|                 } | ||||
|             } | ||||
|             else | ||||
|             { /* Option without a value. */ | ||||
|                 CheckCurPosEnd(state); | ||||
|                 return state->opt; | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| #ifdef TEST_GETOPT | ||||
| 
 | ||||
| #include <stdio.h> | ||||
| 
 | ||||
| int main(int argc, char const * argv[]) | ||||
| { | ||||
|     static int help = 0; | ||||
|     static lsx_option_t longopts[] = | ||||
|     { | ||||
|         {"a11",  0, 0, 101}, | ||||
|         {"a12",  0, 0, 102}, | ||||
|         {"a122", 0, 0, 103}, | ||||
|         {"rarg", 1, 0, 104}, | ||||
|         {"oarg", 2, 0, 105}, | ||||
|         {"help", 0, &help, 106}, | ||||
|         {0} | ||||
|     }; | ||||
| 
 | ||||
|     int ch; | ||||
|     lsx_getopt_t state; | ||||
|     lsx_getopt_init(argc, argv, "abc:d:v::0123456789", longopts, sox_true, 1, &state); | ||||
| 
 | ||||
|     while (-1 != (ch = lsx_getopt(&state))) | ||||
|     { | ||||
|         printf( | ||||
|             "H=%d ch=%d, ind=%d opt=%d lng=%d arg=%s\n", | ||||
|             help, | ||||
|             ch, | ||||
|             state.ind, | ||||
|             state.opt, | ||||
|             state.lngind, | ||||
|             state.arg ? state.arg : "NULL"); | ||||
|     } | ||||
| 
 | ||||
|     return 0; | ||||
| } | ||||
| 
 | ||||
| #endif /* TEST_GETOPT */ | ||||
| @ -1,365 +0,0 @@ | ||||
| /* libSoX ima_rw.c -- codex utilities for WAV_FORMAT_IMA_ADPCM
 | ||||
|  * Copyright (C) 1999 Stanley J. Brooks <stabro@megsinet.net> | ||||
|  * | ||||
|  * This library is free software; you can redistribute it and/or modify it | ||||
|  * under the terms of the GNU Lesser General Public License as published by | ||||
|  * the Free Software Foundation; either version 2.1 of the License, or (at | ||||
|  * your option) any later version. | ||||
|  * | ||||
|  * This library is distributed in the hope that it will be useful, but | ||||
|  * WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser | ||||
|  * General Public License for more details. | ||||
|  * | ||||
|  * You should have received a copy of the GNU Lesser General Public License | ||||
|  * along with this library; if not, write to the Free Software Foundation, | ||||
|  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA | ||||
| 
 | ||||
| */ | ||||
| 
 | ||||
| #include "sox_i.h" | ||||
| #include "ima_rw.h" | ||||
| 
 | ||||
| #include <sys/types.h> | ||||
| #include <stdio.h> | ||||
| #include <stdlib.h> | ||||
| /*
 | ||||
|  * | ||||
|  * Lookup tables for IMA ADPCM format | ||||
|  * | ||||
|  */ | ||||
| #define ISSTMAX 88 | ||||
| 
 | ||||
| static const int imaStepSizeTable[ISSTMAX + 1] = { | ||||
|         7, 8, 9, 10, 11, 12, 13, 14, 16, 17, 19, 21, 23, 25, 28, 31, 34, | ||||
|         37, 41, 45, 50, 55, 60, 66, 73, 80, 88, 97, 107, 118, 130, 143, | ||||
|         157, 173, 190, 209, 230, 253, 279, 307, 337, 371, 408, 449, 494, | ||||
|         544, 598, 658, 724, 796, 876, 963, 1060, 1166, 1282, 1411, 1552, | ||||
|         1707, 1878, 2066, 2272, 2499, 2749, 3024, 3327, 3660, 4026, | ||||
|         4428, 4871, 5358, 5894, 6484, 7132, 7845, 8630, 9493, 10442, | ||||
|         11487, 12635, 13899, 15289, 16818, 18500, 20350, 22385, 24623, | ||||
|         27086, 29794, 32767 | ||||
| }; | ||||
| 
 | ||||
| #define imaStateAdjust(c) (((c)<4)? -1:(2*(c)-6)) | ||||
| /* +0 - +3, decrease step size */ | ||||
| /* +4 - +7, increase step size */ | ||||
| /* -0 - -3, decrease step size */ | ||||
| /* -4 - -7, increase step size */ | ||||
| 
 | ||||
| static unsigned char imaStateAdjustTable[ISSTMAX+1][8]; | ||||
| 
 | ||||
| void lsx_ima_init_table(void) | ||||
| { | ||||
|         int i,j,k; | ||||
|         for (i=0; i<=ISSTMAX; i++) { | ||||
|                 for (j=0; j<8; j++) { | ||||
|                         k = i + imaStateAdjust(j); | ||||
|                         if (k<0) k=0; | ||||
|                         else if (k>ISSTMAX) k=ISSTMAX; | ||||
|                         imaStateAdjustTable[i][j] = k; | ||||
|                 } | ||||
|         } | ||||
| } | ||||
| 
 | ||||
| static void ImaExpandS( | ||||
|         unsigned ch,             /* channel number to decode, REQUIRE 0 <= ch < chans  */ | ||||
|         unsigned chans,          /* total channels             */ | ||||
|         const unsigned char *ibuff,/* input buffer[blockAlign]   */ | ||||
|         SAMPL *obuff,       /* obuff[n] will be output samples */ | ||||
|         int n,              /* samples to decode PER channel, REQUIRE n % 8 == 1  */ | ||||
|         unsigned o_inc           /* index difference between successive output samples */ | ||||
| ) | ||||
| { | ||||
|         const unsigned char *ip; | ||||
|         int i_inc; | ||||
|         SAMPL *op; | ||||
|         int i, val, state; | ||||
| 
 | ||||
|         ip = ibuff + 4*ch;     /* input pointer to 4-byte block state-initializer   */ | ||||
|         i_inc = 4*(chans-1);   /* amount by which to incr ip after each 4-byte read */ | ||||
|         val = (short)(ip[0] + (ip[1]<<8)); /* need cast for sign-extend */ | ||||
|         state = ip[2]; | ||||
|         if (state > ISSTMAX) { | ||||
|                 lsx_warn("IMA_ADPCM block ch%d initial-state (%d) out of range", ch, state); | ||||
|                 state = 0; | ||||
|         } | ||||
|         /* specs say to ignore ip[3] , but write it as 0 */ | ||||
|         ip += 4+i_inc; | ||||
| 
 | ||||
|         op = obuff; | ||||
|         *op = val;      /* 1st output sample for this channel */ | ||||
|         op += o_inc; | ||||
| 
 | ||||
|         for (i = 1; i < n; i++) { | ||||
|                 int step,dp,c,cm; | ||||
| 
 | ||||
|                 if (i&1) {         /* 1st of pair */ | ||||
|                         cm = *ip & 0x0f; | ||||
|                 } else { | ||||
|                         cm = (*ip++)>>4; | ||||
|                         if ((i&7) == 0)  /* ends the 8-sample input block for this channel */ | ||||
|                                 ip += i_inc;   /* skip ip for next group */ | ||||
|                 } | ||||
| 
 | ||||
|                 step = imaStepSizeTable[state]; | ||||
|                 /* Update the state for the next sample */ | ||||
|                 c = cm & 0x07; | ||||
|                 state = imaStateAdjustTable[state][c]; | ||||
| 
 | ||||
|                 dp = 0; | ||||
|                 if (c & 4) dp += step; | ||||
|                 step = step >> 1; | ||||
|                 if (c & 2) dp += step; | ||||
|                 step = step >> 1; | ||||
|                 if (c & 1) dp += step; | ||||
|                 step = step >> 1; | ||||
|                 dp += step; | ||||
| 
 | ||||
|                 if (c != cm) { | ||||
|                         val -= dp; | ||||
|                         if (val<-0x8000) val = -0x8000; | ||||
|                 } else { | ||||
|                         val += dp; | ||||
|                         if (val>0x7fff) val = 0x7fff; | ||||
|                 } | ||||
|                 *op = val; | ||||
|                 op += o_inc; | ||||
|         } | ||||
|         return; | ||||
| } | ||||
| 
 | ||||
| /* lsx_ima_block_expand_i() outputs interleaved samples into one output buffer */ | ||||
| void lsx_ima_block_expand_i( | ||||
|         unsigned chans,          /* total channels             */ | ||||
|         const unsigned char *ibuff,/* input buffer[blockAlign]   */ | ||||
|         SAMPL *obuff,       /* output samples, n*chans    */ | ||||
|         int n               /* samples to decode PER channel, REQUIRE n % 8 == 1  */ | ||||
| ) | ||||
| { | ||||
|         unsigned ch; | ||||
|         for (ch=0; ch<chans; ch++) | ||||
|                 ImaExpandS(ch, chans, ibuff, obuff+ch, n, chans); | ||||
| } | ||||
| 
 | ||||
| /* lsx_ima_block_expand_m() outputs non-interleaved samples into chan separate output buffers */ | ||||
| void lsx_ima_block_expand_m( | ||||
|         unsigned chans,          /* total channels             */ | ||||
|         const unsigned char *ibuff,/* input buffer[blockAlign]   */ | ||||
|         SAMPL **obuffs,     /* chan output sample buffers, each takes n samples */ | ||||
|         int n               /* samples to decode PER channel, REQUIRE n % 8 == 1  */ | ||||
| ) | ||||
| { | ||||
|         unsigned ch; | ||||
|         for (ch=0; ch<chans; ch++) | ||||
|                 ImaExpandS(ch, chans, ibuff, obuffs[ch], n, 1); | ||||
| } | ||||
| 
 | ||||
| static int ImaMashS( | ||||
|         unsigned ch,             /* channel number to encode, REQUIRE 0 <= ch < chans  */ | ||||
|         unsigned chans,          /* total channels */ | ||||
|         int v0,           /* value to use as starting prediction0 */ | ||||
|         const SAMPL *ibuff, /* ibuff[] is interleaved input samples */ | ||||
|         int n,              /* samples to encode PER channel, REQUIRE n % 8 == 1 */ | ||||
|         int *st,            /* input/output state, REQUIRE 0 <= *st <= ISSTMAX */ | ||||
|         unsigned char *obuff /* output buffer[blockAlign], or NULL for no output  */ | ||||
| ) | ||||
| { | ||||
|         const SAMPL *ip, *itop; | ||||
|         unsigned char *op; | ||||
|         int o_inc = 0;      /* set 0 only to shut up gcc's 'might be uninitialized' */ | ||||
|         int i, val; | ||||
|         int state; | ||||
|         double d2;  /* long long is okay also, speed abt the same */ | ||||
| 
 | ||||
|         ip = ibuff + ch;       /* point ip to 1st input sample for this channel */ | ||||
|         itop = ibuff + n*chans; | ||||
|         val = *ip - v0; ip += chans;/* 1st input sample for this channel */ | ||||
|         d2 = val*val;/* d2 will be sum of squares of errors, given input v0 and *st */ | ||||
|         val = v0; | ||||
| 
 | ||||
|         op = obuff;            /* output pointer (or NULL) */ | ||||
|         if (op) {              /* NULL means don't output, just compute the rms error */ | ||||
|                 op += 4*ch;          /* where to put this channel's 4-byte block state-initializer */ | ||||
|                 o_inc = 4*(chans-1); /* amount by which to incr op after each 4-byte written */ | ||||
|                 *op++ = val; *op++ = val>>8; | ||||
|                 *op++ = *st; *op++ = 0; /* they could have put a mid-block state-correction here  */ | ||||
|                 op += o_inc;            /* _sigh_   NEVER waste a byte.      It's a rule!         */ | ||||
|         } | ||||
| 
 | ||||
|         state = *st; | ||||
| 
 | ||||
|         for (i = 0; ip < itop; ip+=chans) { | ||||
|                 int step,d,dp,c; | ||||
| 
 | ||||
|                 d = *ip - val;  /* difference between last prediction and current sample */ | ||||
| 
 | ||||
|                 step = imaStepSizeTable[state]; | ||||
|                 c = (abs(d)<<2)/step; | ||||
|                 if (c > 7) c = 7; | ||||
|                 /* Update the state for the next sample */ | ||||
|                 state = imaStateAdjustTable[state][c]; | ||||
| 
 | ||||
|                 if (op) {   /* if we want output, put it in proper place */ | ||||
|                         int cm = c; | ||||
|                         if (d<0) cm |= 8; | ||||
|                         if (i&1) {       /* odd numbered output */ | ||||
|                                 *op++ |= (cm<<4); | ||||
|                                 if (i == 7)    /* ends the 8-sample output block for this channel */ | ||||
|                                         op += o_inc; /* skip op for next group */ | ||||
|                         } else { | ||||
|                                 *op = cm; | ||||
|                         } | ||||
|                         i = (i+1) & 0x07; | ||||
|                 } | ||||
| 
 | ||||
|                 dp = 0; | ||||
|                 if (c & 4) dp += step; | ||||
|                 step = step >> 1; | ||||
|                 if (c & 2) dp += step; | ||||
|                 step = step >> 1; | ||||
|                 if (c & 1) dp += step; | ||||
|                 step = step >> 1; | ||||
|                 dp += step; | ||||
| 
 | ||||
|                 if (d<0) { | ||||
|                         val -= dp; | ||||
|                         if (val<-0x8000) val = -0x8000; | ||||
|                 } else { | ||||
|                         val += dp; | ||||
|                         if (val>0x7fff) val = 0x7fff; | ||||
|                 } | ||||
| 
 | ||||
|                 { | ||||
|                         int x = *ip - val; | ||||
|                         d2 += x*x; | ||||
|                 } | ||||
| 
 | ||||
|         } | ||||
|         d2 /= n; /* be sure it's non-negative */ | ||||
|         *st = state; | ||||
|         return (int) sqrt(d2); | ||||
| } | ||||
| 
 | ||||
| /* mash one channel... if you want to use opt>0, 9 is a reasonable value */ | ||||
| inline static void ImaMashChannel( | ||||
|         unsigned ch,             /* channel number to encode, REQUIRE 0 <= ch < chans  */ | ||||
|         unsigned chans,          /* total channels */ | ||||
|         const SAMPL *ip,    /* ip[] is interleaved input samples */ | ||||
|         int n,              /* samples to encode PER channel, REQUIRE n % 8 == 1 */ | ||||
|         int *st,            /* input/output state, REQUIRE 0 <= *st <= ISSTMAX */ | ||||
|         unsigned char *obuff, /* output buffer[blockAlign] */ | ||||
|         int opt             /* non-zero allows some cpu-intensive code to improve output */ | ||||
| ) | ||||
| { | ||||
|         int snext; | ||||
|         int s0,d0; | ||||
| 
 | ||||
|         s0 = *st; | ||||
|         if (opt>0) { | ||||
|                 int low,hi,w; | ||||
|                 int low0,hi0; | ||||
|                 snext = s0; | ||||
|                 d0 = ImaMashS(ch, chans, ip[ch], ip,n,&snext, NULL); | ||||
| 
 | ||||
|                 w = 0; | ||||
|                 low=hi=s0; | ||||
|                 low0 = low-opt; if (low0<0) low0=0; | ||||
|                 hi0 = hi+opt; if (hi0>ISSTMAX) hi0=ISSTMAX; | ||||
|                 while (low>low0 || hi<hi0) { | ||||
|                         if (!w && low>low0) { | ||||
|                                 int d2; | ||||
|                                 snext = --low; | ||||
|                                 d2 = ImaMashS(ch, chans, ip[ch], ip,n,&snext, NULL); | ||||
|                                 if (d2<d0) { | ||||
|                                         d0=d2; s0=low; | ||||
|                                         low0 = low-opt; if (low0<0) low0=0; | ||||
|                                         hi0 = low+opt; if (hi0>ISSTMAX) hi0=ISSTMAX; | ||||
|                                 } | ||||
|                         } | ||||
|                         if (w && hi<hi0) { | ||||
|                                 int d2; | ||||
|                                 snext = ++hi; | ||||
|                                 d2 = ImaMashS(ch, chans, ip[ch], ip,n,&snext, NULL); | ||||
|                                 if (d2<d0) { | ||||
|                                         d0=d2; s0=hi; | ||||
|                                         low0 = hi-opt; if (low0<0) low0=0; | ||||
|                                         hi0 = hi+opt; if (hi0>ISSTMAX) hi0=ISSTMAX; | ||||
|                                 } | ||||
|                         } | ||||
|                         w=1-w; | ||||
|                 } | ||||
|                 *st = s0; | ||||
|         } | ||||
|         ImaMashS(ch, chans, ip[ch], ip,n,st, obuff); | ||||
| } | ||||
| 
 | ||||
| /* mash one block.  if you want to use opt>0, 9 is a reasonable value */ | ||||
| void lsx_ima_block_mash_i( | ||||
|         unsigned chans,          /* total channels */ | ||||
|         const SAMPL *ip,    /* ip[] is interleaved input samples */ | ||||
|         int n,              /* samples to encode PER channel, REQUIRE n % 8 == 1 */ | ||||
|         int *st,            /* input/output state, REQUIRE 0 <= *st <= ISSTMAX */ | ||||
|         unsigned char *obuff, /* output buffer[blockAlign] */ | ||||
|         int opt             /* non-zero allows some cpu-intensive code to improve output */ | ||||
| ) | ||||
| { | ||||
|         unsigned ch; | ||||
|         for (ch=0; ch<chans; ch++) | ||||
|                 ImaMashChannel(ch, chans, ip, n, st+ch, obuff, opt); | ||||
| } | ||||
| 
 | ||||
| /*
 | ||||
|  * lsx_ima_samples_in(dataLen, chans, blockAlign, samplesPerBlock) | ||||
|  *  returns the number of samples/channel which would go | ||||
|  *  in the dataLen, given the other parameters ... | ||||
|  *  if input samplesPerBlock is 0, then returns the max | ||||
|  *  samplesPerBlock which would go into a block of size blockAlign | ||||
|  *  Yes, it is confusing. | ||||
|  */ | ||||
| size_t lsx_ima_samples_in( | ||||
|   size_t dataLen, | ||||
|   size_t chans, | ||||
|   size_t blockAlign, | ||||
|   size_t samplesPerBlock | ||||
| ) | ||||
| { | ||||
|   size_t m, n; | ||||
| 
 | ||||
|   if (samplesPerBlock) { | ||||
|     n = (dataLen / blockAlign) * samplesPerBlock; | ||||
|     m = (dataLen % blockAlign); | ||||
|   } else { | ||||
|     n = 0; | ||||
|     m = blockAlign; | ||||
|   } | ||||
|   if (m >= (size_t)4*chans) { | ||||
|     m -= 4*chans;    /* number of bytes beyond block-header */ | ||||
|     m /= 4*chans;    /* number of 4-byte blocks/channel beyond header */ | ||||
|     m = 8*m + 1;     /* samples/chan beyond header + 1 in header */ | ||||
|     if (samplesPerBlock && m > samplesPerBlock) m = samplesPerBlock; | ||||
|     n += m; | ||||
|   } | ||||
|   return n; | ||||
|   /*wSamplesPerBlock = ((wBlockAlign - 4*wChannels)/(4*wChannels))*8 + 1;*/ | ||||
| } | ||||
| 
 | ||||
| /*
 | ||||
|  * size_t lsx_ima_bytes_per_block(chans, samplesPerBlock) | ||||
|  *   return minimum blocksize which would be required | ||||
|  *   to encode number of chans with given samplesPerBlock | ||||
|  */ | ||||
| size_t lsx_ima_bytes_per_block( | ||||
|   size_t chans, | ||||
|   size_t samplesPerBlock | ||||
| ) | ||||
| { | ||||
|   size_t n; | ||||
|   /* per channel, ima has blocks of len 4, the 1st has 1st sample, the others
 | ||||
|    * up to 8 samples per block, | ||||
|    * so number of later blocks is (nsamp-1 + 7)/8, total blocks/chan is | ||||
|    * (nsamp-1+7)/8 + 1 = (nsamp+14)/8 | ||||
|    */ | ||||
|   n = ((size_t)samplesPerBlock + 14)/8 * 4 * chans; | ||||
|   return n; | ||||
| } | ||||
| @ -1,84 +0,0 @@ | ||||
| /* libSoX ima_rw.h -- codex utilities for WAV_FORMAT_IMA_ADPCM
 | ||||
|  * Copyright (C) 1999 Stanley J. Brooks <stabro@megsinet.net> | ||||
|  * | ||||
|  * This library is free software; you can redistribute it and/or modify it | ||||
|  * under the terms of the GNU Lesser General Public License as published by | ||||
|  * the Free Software Foundation; either version 2.1 of the License, or (at | ||||
|  * your option) any later version. | ||||
|  * | ||||
|  * This library is distributed in the hope that it will be useful, but | ||||
|  * WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser | ||||
|  * General Public License for more details. | ||||
|  * | ||||
|  * You should have received a copy of the GNU Lesser General Public License | ||||
|  * along with this library; if not, write to the Free Software Foundation, | ||||
|  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA | ||||
| 
 | ||||
| */ | ||||
| 
 | ||||
| #include "sox.h" | ||||
| 
 | ||||
| #ifndef SAMPL | ||||
| #define SAMPL short | ||||
| #endif | ||||
| 
 | ||||
| /*
 | ||||
|  * call lsx_ima_init_table() before any other Ima* functions, | ||||
|  * to create the fast lookup tables | ||||
|  */ | ||||
| extern void lsx_ima_init_table(void); | ||||
| 
 | ||||
| /* lsx_ima_block_expand_i() outputs interleaved samples into one output buffer */ | ||||
| extern void lsx_ima_block_expand_i( | ||||
| 	unsigned chans,          /* total channels             */ | ||||
| 	const unsigned char *ibuff,/* input buffer[blockAlign]   */ | ||||
| 	SAMPL *obuff,       /* output samples, n*chans    */ | ||||
| 	int n               /* samples to decode PER channel, REQUIRE n % 8 == 1  */ | ||||
| ); | ||||
| 
 | ||||
| /* lsx_ima_block_expand_m() outputs non-interleaved samples into chan separate output buffers */ | ||||
| extern void lsx_ima_block_expand_m( | ||||
| 	unsigned chans,          /* total channels             */ | ||||
| 	const unsigned char *ibuff,/* input buffer[blockAlign]   */ | ||||
| 	SAMPL **obuffs,     /* chan output sample buffers, each takes n samples */ | ||||
| 	int n               /* samples to decode PER channel, REQUIRE n % 8 == 1  */ | ||||
| ); | ||||
| 
 | ||||
| /* mash one block.  if you want to use opt>0, 9 is a reasonable value */ | ||||
| extern void lsx_ima_block_mash_i( | ||||
| 	unsigned chans,          /* total channels */ | ||||
| 	const SAMPL *ip,    /* ip[] is interleaved input samples */ | ||||
| 	int n,              /* samples to encode PER channel, REQUIRE n % 8 == 1 */ | ||||
| 	int *st,            /* input/output state[chans], REQUIRE 0 <= st[ch] <= ISSTMAX */ | ||||
| 	unsigned char *obuff, /* output buffer[blockAlign] */ | ||||
| 	int opt             /* non-zero allows some cpu-intensive code to improve output */ | ||||
| ); | ||||
| 
 | ||||
| /* Some helper functions for computing samples/block and blockalign */ | ||||
| 
 | ||||
| /*
 | ||||
|  * lsx_ima_samples_in(dataLen, chans, blockAlign, samplesPerBlock) | ||||
|  *  returns the number of samples/channel which would go | ||||
|  *  in the dataLen, given the other parameters ... | ||||
|  *  if input samplesPerBlock is 0, then returns the max | ||||
|  *  samplesPerBlock which would go into a block of size blockAlign | ||||
|  *  Yes, it is confusing usage. | ||||
|  */ | ||||
| extern size_t lsx_ima_samples_in( | ||||
| 	size_t dataLen, | ||||
| 	size_t chans, | ||||
| 	size_t blockAlign, | ||||
| 	size_t samplesPerBlock | ||||
| ); | ||||
| 
 | ||||
| /*
 | ||||
|  * size_t lsx_ima_bytes_per_block(chans, samplesPerBlock) | ||||
|  *   return minimum blocksize which would be required | ||||
|  *   to encode number of chans with given samplesPerBlock | ||||
|  */ | ||||
| extern size_t lsx_ima_bytes_per_block( | ||||
| 	size_t chans, | ||||
| 	size_t samplesPerBlock | ||||
| ); | ||||
| 
 | ||||
| @ -1,58 +0,0 @@ | ||||
| /* libSoX effect: Input audio from a file   (c) 2008 robs@users.sourceforge.net
 | ||||
|  * | ||||
|  * This library is free software; you can redistribute it and/or modify it | ||||
|  * under the terms of the GNU Lesser General Public License as published by | ||||
|  * the Free Software Foundation; either version 2.1 of the License, or (at | ||||
|  * your option) any later version. | ||||
|  * | ||||
|  * This library is distributed in the hope that it will be useful, but | ||||
|  * WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser | ||||
|  * General Public License for more details. | ||||
|  * | ||||
|  * You should have received a copy of the GNU Lesser General Public License | ||||
|  * along with this library; if not, write to the Free Software Foundation, | ||||
|  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA | ||||
|  */ | ||||
| 
 | ||||
| #include "sox_i.h" | ||||
| 
 | ||||
| typedef struct {sox_format_t * file;} priv_t; | ||||
| 
 | ||||
| static int getopts(sox_effect_t * effp, int argc, char * * argv) | ||||
| { | ||||
|   priv_t * p = (priv_t *)effp->priv; | ||||
|   if (argc != 2 || !(p->file = (sox_format_t *)argv[1]) || p->file->mode != 'r') | ||||
|     return SOX_EOF; | ||||
|   return SOX_SUCCESS; | ||||
| } | ||||
| 
 | ||||
| static int drain( | ||||
|     sox_effect_t * effp, sox_sample_t * obuf, size_t * osamp) | ||||
| { | ||||
|   priv_t * p = (priv_t *)effp->priv; | ||||
| 
 | ||||
|   /* ensure that *osamp is a multiple of the number of channels. */ | ||||
|   *osamp -= *osamp % effp->out_signal.channels; | ||||
| 
 | ||||
|   /* Read up to *osamp samples into obuf; store the actual number read
 | ||||
|    * back to *osamp */ | ||||
|   *osamp = sox_read(p->file, obuf, *osamp); | ||||
| 
 | ||||
|   /* sox_read may return a number that is less than was requested; only if
 | ||||
|    * 0 samples is returned does it indicate that end-of-file has been reached | ||||
|    * or an error has occurred */ | ||||
|   if (!*osamp && p->file->sox_errno) | ||||
|     lsx_fail("%s: %s", p->file->filename, p->file->sox_errstr); | ||||
|   return *osamp? SOX_SUCCESS : SOX_EOF; | ||||
| } | ||||
| 
 | ||||
| sox_effect_handler_t const * lsx_input_effect_fn(void) | ||||
| { | ||||
|   static sox_effect_handler_t handler = { | ||||
|     "input", NULL, SOX_EFF_MCHAN | SOX_EFF_LENGTH | SOX_EFF_INTERNAL, | ||||
|     getopts, NULL, NULL, drain, NULL, NULL, sizeof(priv_t) | ||||
|   }; | ||||
|   return &handler; | ||||
| } | ||||
| 
 | ||||
| @ -1,224 +0,0 @@ | ||||
| /* Implements the public API for libSoX general functions
 | ||||
|  * All public functions & data are prefixed with sox_ . | ||||
|  * | ||||
|  * (c) 2006-8 Chris Bagwell and SoX contributors | ||||
|  * | ||||
|  * This library is free software; you can redistribute it and/or modify it | ||||
|  * under the terms of the GNU Lesser General Public License as published by | ||||
|  * the Free Software Foundation; either version 2.1 of the License, or (at | ||||
|  * your option) any later version. | ||||
|  * | ||||
|  * This library is distributed in the hope that it will be useful, but | ||||
|  * WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser | ||||
|  * General Public License for more details. | ||||
|  * | ||||
|  * You should have received a copy of the GNU Lesser General Public License | ||||
|  * along with this library; if not, write to the Free Software Foundation, | ||||
|  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA | ||||
|  */ | ||||
| 
 | ||||
| #include "sox_i.h" | ||||
| #include <string.h> | ||||
| 
 | ||||
| const char *sox_version(void) | ||||
| { | ||||
|   static char versionstr[20]; | ||||
| 
 | ||||
|   sprintf(versionstr, "%d.%d.%d", | ||||
|           (SOX_LIB_VERSION_CODE & 0xff0000) >> 16, | ||||
|           (SOX_LIB_VERSION_CODE & 0x00ff00) >> 8, | ||||
|           (SOX_LIB_VERSION_CODE & 0x0000ff)); | ||||
|   return(versionstr); | ||||
| } | ||||
| 
 | ||||
| sox_version_info_t const * sox_version_info(void) | ||||
| { | ||||
| #define STRINGIZE1(x) #x | ||||
| #define STRINGIZE(x) STRINGIZE1(x) | ||||
|     static char arch[30]; | ||||
|     static sox_version_info_t info = { | ||||
|         /* size */ | ||||
|         sizeof(sox_version_info_t), | ||||
|         /* flags */ | ||||
|         (sox_version_flags_t)( | ||||
| #if HAVE_POPEN | ||||
|         sox_version_have_popen + | ||||
| #endif | ||||
| #if  HAVE_MAGIC | ||||
|         sox_version_have_magic + | ||||
| #endif | ||||
| #if HAVE_OPENMP | ||||
|         sox_version_have_threads + | ||||
| #endif | ||||
| #ifdef HAVE_FMEMOPEN | ||||
|         sox_version_have_memopen + | ||||
| #endif | ||||
|         sox_version_none), | ||||
|         /* version_code */ | ||||
|         SOX_LIB_VERSION_CODE, | ||||
|         /* version */ | ||||
|         NULL, | ||||
|         /* sox_version_extra */ | ||||
| #ifdef PACKAGE_EXTRA | ||||
|         PACKAGE_EXTRA, | ||||
| #else | ||||
|         NULL, | ||||
| #endif | ||||
|         /* sox_time */ | ||||
|         __DATE__ " " __TIME__, | ||||
|         /* sox_distro */ | ||||
| #ifdef DISTRO | ||||
|         DISTRO, | ||||
| #else | ||||
|         NULL, | ||||
| #endif | ||||
|         /* sox_compiler */ | ||||
| #if defined __GNUC__ | ||||
|         "gcc " __VERSION__, | ||||
| #elif defined _MSC_VER | ||||
|         "msvc " STRINGIZE(_MSC_FULL_VER), | ||||
| #elif defined __SUNPRO_C | ||||
|     fprintf(file, "sun c " STRINGIZE(__SUNPRO_C), | ||||
| #else | ||||
|         NULL, | ||||
| #endif | ||||
|         /* sox_arch */ | ||||
|         NULL | ||||
|     }; | ||||
| 
 | ||||
|     if (!info.version) | ||||
|     { | ||||
|         info.version = sox_version(); | ||||
|     } | ||||
| 
 | ||||
|     if (!info.arch) | ||||
|     { | ||||
|         snprintf(arch, sizeof(arch), | ||||
|             "%" PRIuPTR "%" PRIuPTR "%" PRIuPTR "%" PRIuPTR | ||||
|             " %" PRIuPTR "%" PRIuPTR " %" PRIuPTR "%" PRIuPTR " %c %s", | ||||
|             sizeof(char), sizeof(short), sizeof(long), sizeof(off_t), | ||||
|             sizeof(float), sizeof(double), sizeof(int *), sizeof(int (*)(void)), | ||||
|             MACHINE_IS_BIGENDIAN ? 'B' : 'L', | ||||
|             (info.flags & sox_version_have_threads) ? "OMP" : ""); | ||||
|         arch[sizeof(arch) - 1] = 0; | ||||
|         info.arch = arch; | ||||
|     } | ||||
| 
 | ||||
|     return &info; | ||||
| } | ||||
| 
 | ||||
| /* Default routine to output messages; can be overridden */ | ||||
| static void output_message( | ||||
|     unsigned level, const char *filename, const char *fmt, va_list ap) | ||||
| { | ||||
|   if (sox_globals.verbosity >= level) { | ||||
|     char base_name[128]; | ||||
|     sox_basename(base_name, sizeof(base_name), filename); | ||||
|     fprintf(stderr, "%s: ", base_name); | ||||
|     vfprintf(stderr, fmt, ap); | ||||
|     fprintf(stderr, "\n"); | ||||
|   } | ||||
| } | ||||
| 
 | ||||
| static sox_globals_t s_sox_globals = { | ||||
|   2,               /* unsigned     verbosity */ | ||||
|   output_message,  /* sox_output_message_handler */ | ||||
|   sox_false,       /* sox_bool     repeatable */ | ||||
|   8192,            /* size_t       bufsiz */ | ||||
|   0,               /* size_t       input_bufsiz */ | ||||
|   0,               /* int32_t      ranqd1 */ | ||||
|   NULL,            /* char const * stdin_in_use_by */ | ||||
|   NULL,            /* char const * stdout_in_use_by */ | ||||
|   NULL,            /* char const * subsystem */ | ||||
|   NULL,            /* char       * tmp_path */ | ||||
|   sox_false,       /* sox_bool     use_magic */ | ||||
|   sox_false,       /* sox_bool     use_threads */ | ||||
|   10               /* size_t       log2_dft_min_size */ | ||||
| }; | ||||
| 
 | ||||
| sox_globals_t * sox_get_globals(void) | ||||
| { | ||||
|     return &s_sox_globals; | ||||
| } | ||||
| 
 | ||||
| /* FIXME: Not thread safe using globals */ | ||||
| static sox_effects_globals_t s_sox_effects_globals = | ||||
|     {sox_plot_off, &s_sox_globals}; | ||||
| 
 | ||||
| sox_effects_globals_t * | ||||
| sox_get_effects_globals(void) | ||||
| { | ||||
|     return &s_sox_effects_globals; | ||||
| } | ||||
| 
 | ||||
| char const * sox_strerror(int sox_errno) | ||||
| { | ||||
|   static char const * const errors[] = { | ||||
|     "Invalid Audio Header", | ||||
|     "Unsupported data format", | ||||
|     "Can't allocate memory", | ||||
|     "Operation not permitted", | ||||
|     "Operation not supported", | ||||
|     "Invalid argument", | ||||
|   }; | ||||
|   if (sox_errno < SOX_EHDR) | ||||
|     return strerror(sox_errno); | ||||
|   sox_errno -= SOX_EHDR; | ||||
|   if (sox_errno < 0 || (size_t)sox_errno >= array_length(errors)) | ||||
|     return "Unknown error"; | ||||
|   return errors[sox_errno]; | ||||
| } | ||||
| 
 | ||||
| size_t sox_basename(char * base_buffer, size_t base_buffer_len, const char * filename) | ||||
| { | ||||
|   if (!base_buffer || !base_buffer_len) | ||||
|   { | ||||
|     return 0; | ||||
|   } | ||||
|   else | ||||
|   { | ||||
|     char const * slash_pos = LAST_SLASH(filename); | ||||
|     char const * base_name = slash_pos ? slash_pos + 1 : filename; | ||||
|     char const * dot_pos   = strrchr(base_name, '.'); | ||||
|     size_t i, len; | ||||
|     dot_pos = dot_pos ? dot_pos : base_name + strlen(base_name); | ||||
|     len = dot_pos - base_name; | ||||
|     len = min(len, base_buffer_len - 1); | ||||
|     for (i = 0; i < len; i++) | ||||
|     { | ||||
|       base_buffer[i] = base_name[i]; | ||||
|     } | ||||
|     base_buffer[i] = 0; | ||||
|     return i; | ||||
|   } | ||||
| } | ||||
| 
 | ||||
| #define SOX_MESSAGE_FUNCTION(name,level) \ | ||||
| void name(char const * fmt, ...) { \
 | ||||
|   va_list ap; \
 | ||||
|   va_start(ap, fmt); \
 | ||||
|   if (sox_globals.output_message_handler) \
 | ||||
|     (*sox_globals.output_message_handler)(level,sox_globals.subsystem,fmt,ap); \
 | ||||
|   va_end(ap); \
 | ||||
| } | ||||
| 
 | ||||
| SOX_MESSAGE_FUNCTION(lsx_fail_impl  , 1) | ||||
| SOX_MESSAGE_FUNCTION(lsx_warn_impl  , 2) | ||||
| SOX_MESSAGE_FUNCTION(lsx_report_impl, 3) | ||||
| SOX_MESSAGE_FUNCTION(lsx_debug_impl , 4) | ||||
| SOX_MESSAGE_FUNCTION(lsx_debug_more_impl , 5) | ||||
| SOX_MESSAGE_FUNCTION(lsx_debug_most_impl , 6) | ||||
| 
 | ||||
| #undef SOX_MESSAGE_FUNCTION | ||||
| 
 | ||||
| int sox_init(void) | ||||
| { | ||||
|   return lsx_effects_init(); | ||||
| } | ||||
| 
 | ||||
| int sox_quit(void) | ||||
| { | ||||
|   sox_format_quit(); | ||||
|   return lsx_effects_quit(); | ||||
| } | ||||
| @ -1,116 +0,0 @@ | ||||
| /* libSoX internal functions that apply to both formats and effects
 | ||||
|  * All public functions & data are prefixed with lsx_ . | ||||
|  * | ||||
|  * Copyright (c) 2008 robs@users.sourceforge.net | ||||
|  * | ||||
|  * This library is free software; you can redistribute it and/or modify it | ||||
|  * under the terms of the GNU Lesser General Public License as published by | ||||
|  * the Free Software Foundation; either version 2.1 of the License, or (at | ||||
|  * your option) any later version. | ||||
|  * | ||||
|  * This library is distributed in the hope that it will be useful, but | ||||
|  * WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser | ||||
|  * General Public License for more details. | ||||
|  * | ||||
|  * You should have received a copy of the GNU Lesser General Public License | ||||
|  * along with this library; if not, write to the Free Software Foundation, | ||||
|  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA | ||||
|  */ | ||||
| 
 | ||||
| 
 | ||||
| #include "sox_i.h" | ||||
| 
 | ||||
| #ifdef HAVE_IO_H | ||||
|   #include <io.h> | ||||
| #endif | ||||
| 
 | ||||
| #ifdef HAVE_UNISTD_H | ||||
|   #include <unistd.h> | ||||
| #endif | ||||
| 
 | ||||
| #if defined(_MSC_VER) || defined(__MINGW32__) | ||||
|   #define MKTEMP_X _O_BINARY|_O_TEMPORARY | ||||
| #else | ||||
|   #define MKTEMP_X 0 | ||||
| #endif | ||||
| 
 | ||||
| #ifndef HAVE_MKSTEMP | ||||
|   #include <fcntl.h> | ||||
|   #include <sys/types.h> | ||||
|   #include <sys/stat.h> | ||||
|   #define mkstemp(t) open(mktemp(t), MKTEMP_X|O_RDWR|O_TRUNC|O_CREAT, S_IREAD|S_IWRITE) | ||||
|   #define FAKE_MKSTEMP "fake " | ||||
| #else | ||||
|   #define FAKE_MKSTEMP | ||||
| #endif | ||||
| 
 | ||||
| #ifdef WIN32 | ||||
| static int check_dir(char * buf, size_t buflen, char const * name) | ||||
| { | ||||
|   struct stat st; | ||||
|   if (!name || stat(name, &st) || (st.st_mode & S_IFMT) != S_IFDIR) | ||||
|   { | ||||
|     return 0; | ||||
|   } | ||||
|   else | ||||
|   { | ||||
|     strncpy(buf, name, buflen); | ||||
|     buf[buflen - 1] = 0; | ||||
|     return strlen(name) == strlen(buf); | ||||
|   } | ||||
| } | ||||
| #endif | ||||
| 
 | ||||
| FILE * lsx_tmpfile(void) | ||||
| { | ||||
|   char const * path = sox_globals.tmp_path; | ||||
| 
 | ||||
|   /*
 | ||||
|   On Win32, tmpfile() is broken - it creates the file in the root directory of | ||||
|   the current drive (the user probably doesn't have permission to write there!) | ||||
|   instead of in a valid temporary directory (like TEMP or TMP). So if tmp_path | ||||
|   is null, figure out a reasonable default. | ||||
|   To force use of tmpfile(), set sox_globals.tmp_path = "". | ||||
|   */ | ||||
| #ifdef WIN32 | ||||
|   if (!path) | ||||
|   { | ||||
|     static char default_path[260] = ""; | ||||
|     if (default_path[0] == 0 | ||||
|         && !check_dir(default_path, sizeof(default_path), getenv("TEMP")) | ||||
|         && !check_dir(default_path, sizeof(default_path), getenv("TMP")) | ||||
|     #ifdef __CYGWIN__ | ||||
|         && !check_dir(default_path, sizeof(default_path), "/tmp") | ||||
|     #endif | ||||
|         ) | ||||
|     { | ||||
|       strcpy(default_path, "."); | ||||
|     } | ||||
| 
 | ||||
|     path = default_path; | ||||
|   } | ||||
| #endif | ||||
| 
 | ||||
|   if (path && path[0]) { | ||||
|     /* Emulate tmpfile (delete on close); tmp dir is given tmp_path: */ | ||||
|     char const * const end = "/libSoX.tmp.XXXXXX"; | ||||
|     char * name = lsx_malloc(strlen(path) + strlen(end) + 1); | ||||
|     int fildes; | ||||
|     strcpy(name, path); | ||||
|     strcat(name, end); | ||||
|     fildes = mkstemp(name); | ||||
| #ifdef HAVE_UNISTD_H | ||||
|     lsx_debug(FAKE_MKSTEMP "mkstemp, name=%s (unlinked)", name); | ||||
|     unlink(name); | ||||
| #else | ||||
|     lsx_debug(FAKE_MKSTEMP "mkstemp, name=%s (O_TEMPORARY)", name); | ||||
| #endif | ||||
|     free(name); | ||||
|     return fildes == -1? NULL : fdopen(fildes, "w+b"); | ||||
|   } | ||||
| 
 | ||||
|   /* Use standard tmpfile (delete on close); tmp dir is undefined: */ | ||||
|   lsx_debug("tmpfile()"); | ||||
|   return tmpfile(); | ||||
| } | ||||
| @ -1,59 +0,0 @@ | ||||
| /* libSoX effect: Output audio to a file   (c) 2008 robs@users.sourceforge.net
 | ||||
|  * | ||||
|  * This library is free software; you can redistribute it and/or modify it | ||||
|  * under the terms of the GNU Lesser General Public License as published by | ||||
|  * the Free Software Foundation; either version 2.1 of the License, or (at | ||||
|  * your option) any later version. | ||||
|  * | ||||
|  * This library is distributed in the hope that it will be useful, but | ||||
|  * WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser | ||||
|  * General Public License for more details. | ||||
|  * | ||||
|  * You should have received a copy of the GNU Lesser General Public License | ||||
|  * along with this library; if not, write to the Free Software Foundation, | ||||
|  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA | ||||
|  */ | ||||
| 
 | ||||
| #include "sox_i.h" | ||||
| 
 | ||||
| typedef struct {sox_format_t * file;} priv_t; | ||||
| 
 | ||||
| static int getopts(sox_effect_t * effp, int argc, char * * argv) | ||||
| { | ||||
|   priv_t * p = (priv_t *)effp->priv; | ||||
|   if (argc != 2 || !(p->file = (sox_format_t *)argv[1]) || p->file->mode != 'w') | ||||
|     return SOX_EOF; | ||||
|   return SOX_SUCCESS; | ||||
| } | ||||
| 
 | ||||
| static int flow(sox_effect_t *effp, sox_sample_t const * ibuf, | ||||
|     sox_sample_t * obuf, size_t * isamp, size_t * osamp) | ||||
| { | ||||
|   priv_t * p = (priv_t *)effp->priv; | ||||
|   /* Write out *isamp samples */ | ||||
|   size_t len = sox_write(p->file, ibuf, *isamp); | ||||
| 
 | ||||
|   /* len is the number of samples that were actually written out; if this is
 | ||||
|    * different to *isamp, then something has gone wrong--most often, it's | ||||
|    * out of disc space */ | ||||
|   if (len != *isamp) { | ||||
|     lsx_fail("%s: %s", p->file->filename, p->file->sox_errstr); | ||||
|     return SOX_EOF; | ||||
|   } | ||||
| 
 | ||||
|   /* Outputting is the last `effect' in the effect chain so always passes
 | ||||
|    * 0 samples on to the next effect (as there isn't one!) */ | ||||
|   (void)obuf, *osamp = 0; | ||||
|   return SOX_SUCCESS; /* All samples output successfully */ | ||||
| } | ||||
| 
 | ||||
| sox_effect_handler_t const * lsx_output_effect_fn(void) | ||||
| { | ||||
|   static sox_effect_handler_t handler = { | ||||
|     "output", NULL, SOX_EFF_MCHAN | SOX_EFF_INTERNAL, | ||||
|     getopts, NULL, flow, NULL, NULL, NULL, sizeof(priv_t) | ||||
|   }; | ||||
|   return &handler; | ||||
| } | ||||
| 
 | ||||
| @ -1,196 +0,0 @@ | ||||
| /* libSoX raw I/O
 | ||||
|  * | ||||
|  * Copyright 1991-2007 Lance Norskog And Sundry Contributors | ||||
|  * This source code is freely redistributable and may be used for | ||||
|  * any purpose.  This copyright notice must be maintained. | ||||
|  * Lance Norskog And Sundry Contributors are not responsible for | ||||
|  * the consequences of using this software. | ||||
|  */ | ||||
| 
 | ||||
| #include "sox_i.h" | ||||
| #include "g711.h" | ||||
| 
 | ||||
| typedef sox_uint16_t sox_uint14_t; | ||||
| typedef sox_uint16_t sox_uint13_t; | ||||
| typedef sox_int16_t sox_int14_t; | ||||
| typedef sox_int16_t sox_int13_t; | ||||
| #define SOX_ULAW_BYTE_TO_SAMPLE(d,clips)   SOX_SIGNED_16BIT_TO_SAMPLE(sox_ulaw2linear16(d),clips) | ||||
| #define SOX_ALAW_BYTE_TO_SAMPLE(d,clips)   SOX_SIGNED_16BIT_TO_SAMPLE(sox_alaw2linear16(d),clips) | ||||
| #define SOX_SAMPLE_TO_ULAW_BYTE(d,c) sox_14linear2ulaw(SOX_SAMPLE_TO_UNSIGNED(14,d,c) - 0x2000) | ||||
| #define SOX_SAMPLE_TO_ALAW_BYTE(d,c) sox_13linear2alaw(SOX_SAMPLE_TO_UNSIGNED(13,d,c) - 0x1000) | ||||
| 
 | ||||
| int lsx_rawseek(sox_format_t * ft, uint64_t offset) | ||||
| { | ||||
|   return lsx_offset_seek(ft, (off_t)ft->data_start, (off_t)offset); | ||||
| } | ||||
| 
 | ||||
| /* Works nicely for starting read and write; lsx_rawstart{read,write}
 | ||||
|  * are #defined in sox_i.h */ | ||||
| int lsx_rawstart(sox_format_t * ft, sox_bool default_rate, | ||||
|                  sox_bool default_channels, sox_bool default_length, | ||||
|                  sox_encoding_t encoding, unsigned size) | ||||
| { | ||||
|   if (default_rate && ft->signal.rate == 0) { | ||||
|     lsx_warn("`%s': sample rate not specified; trying 8kHz", ft->filename); | ||||
|     ft->signal.rate = 8000; | ||||
|   } | ||||
| 
 | ||||
|   if (default_channels && ft->signal.channels == 0) { | ||||
|     lsx_warn("`%s': # channels not specified; trying mono", ft->filename); | ||||
|     ft->signal.channels = 1; | ||||
|   } | ||||
| 
 | ||||
|   if (encoding != SOX_ENCODING_UNKNOWN) { | ||||
|     if (ft->mode == 'r' && ft->encoding.encoding != SOX_ENCODING_UNKNOWN && | ||||
|         ft->encoding.encoding != encoding) | ||||
|       lsx_report("`%s': Format options overriding file-type encoding", | ||||
|                  ft->filename); | ||||
|     else | ||||
|       ft->encoding.encoding = encoding; | ||||
|   } | ||||
| 
 | ||||
|   if (size != 0) { | ||||
|     if (ft->mode == 'r' && ft->encoding.bits_per_sample != 0 && | ||||
|         ft->encoding.bits_per_sample != size) | ||||
|       lsx_report("`%s': Format options overriding file-type sample-size", | ||||
|                  ft->filename); | ||||
|     else | ||||
|       ft->encoding.bits_per_sample = size; | ||||
|   } | ||||
| 
 | ||||
|   if (!ft->signal.length && ft->mode == 'r' && default_length && | ||||
|       ft->encoding.bits_per_sample) | ||||
|     ft->signal.length = | ||||
|         div_bits(lsx_filelength(ft), ft->encoding.bits_per_sample); | ||||
| 
 | ||||
|   return SOX_SUCCESS; | ||||
| } | ||||
| 
 | ||||
| #define READ_SAMPLES_FUNC(type, size, sign, ctype, uctype, cast) \ | ||||
|   static size_t sox_read_ ## sign ## type ## _samples( \
 | ||||
|       sox_format_t * ft, sox_sample_t *buf, size_t len) \
 | ||||
|   { \
 | ||||
|     size_t n, nread; \
 | ||||
|     SOX_SAMPLE_LOCALS; \
 | ||||
|     ctype *data = lsx_malloc(sizeof(ctype) * len); \
 | ||||
|     LSX_USE_VAR(sox_macro_temp_sample), LSX_USE_VAR(sox_macro_temp_double); \
 | ||||
|     nread = lsx_read_ ## type ## _buf(ft, (uctype *)data, len); \
 | ||||
|     for (n = 0; n < nread; n++) \
 | ||||
|       *buf++ = cast(data[n], ft->clips); \
 | ||||
|     free(data); \
 | ||||
|     return nread; \
 | ||||
|   } | ||||
| 
 | ||||
| READ_SAMPLES_FUNC(b, 1, u, uint8_t, uint8_t, SOX_UNSIGNED_8BIT_TO_SAMPLE) | ||||
| READ_SAMPLES_FUNC(b, 1, s, int8_t, uint8_t, SOX_SIGNED_8BIT_TO_SAMPLE) | ||||
| READ_SAMPLES_FUNC(b, 1, ulaw, uint8_t, uint8_t, SOX_ULAW_BYTE_TO_SAMPLE) | ||||
| READ_SAMPLES_FUNC(b, 1, alaw, uint8_t, uint8_t, SOX_ALAW_BYTE_TO_SAMPLE) | ||||
| READ_SAMPLES_FUNC(w, 2, u, uint16_t, uint16_t, SOX_UNSIGNED_16BIT_TO_SAMPLE) | ||||
| READ_SAMPLES_FUNC(w, 2, s, int16_t, uint16_t, SOX_SIGNED_16BIT_TO_SAMPLE) | ||||
| READ_SAMPLES_FUNC(3, 3, u, sox_uint24_t, sox_uint24_t, SOX_UNSIGNED_24BIT_TO_SAMPLE) | ||||
| READ_SAMPLES_FUNC(3, 3, s, sox_int24_t, sox_uint24_t, SOX_SIGNED_24BIT_TO_SAMPLE) | ||||
| READ_SAMPLES_FUNC(dw, 4, u, uint32_t, uint32_t, SOX_UNSIGNED_32BIT_TO_SAMPLE) | ||||
| READ_SAMPLES_FUNC(dw, 4, s, int32_t, uint32_t, SOX_SIGNED_32BIT_TO_SAMPLE) | ||||
| READ_SAMPLES_FUNC(f, sizeof(float), su, float, float, SOX_FLOAT_32BIT_TO_SAMPLE) | ||||
| READ_SAMPLES_FUNC(df, sizeof(double), su, double, double, SOX_FLOAT_64BIT_TO_SAMPLE) | ||||
| 
 | ||||
| #define WRITE_SAMPLES_FUNC(type, size, sign, ctype, uctype, cast) \ | ||||
|   static size_t sox_write_ ## sign ## type ## _samples( \
 | ||||
|       sox_format_t * ft, sox_sample_t const * buf, size_t len) \
 | ||||
|   { \
 | ||||
|     SOX_SAMPLE_LOCALS; \
 | ||||
|     size_t n, nwritten; \
 | ||||
|     ctype *data = lsx_malloc(sizeof(ctype) * len); \
 | ||||
|     LSX_USE_VAR(sox_macro_temp_sample), LSX_USE_VAR(sox_macro_temp_double); \
 | ||||
|     for (n = 0; n < len; n++) \
 | ||||
|       data[n] = cast(buf[n], ft->clips); \
 | ||||
|     nwritten = lsx_write_ ## type ## _buf(ft, (uctype *)data, len); \
 | ||||
|     free(data); \
 | ||||
|     return nwritten; \
 | ||||
|   } | ||||
| 
 | ||||
| 
 | ||||
| WRITE_SAMPLES_FUNC(b, 1, u, uint8_t, uint8_t, SOX_SAMPLE_TO_UNSIGNED_8BIT) 
 | ||||
| WRITE_SAMPLES_FUNC(b, 1, s, int8_t, uint8_t, SOX_SAMPLE_TO_SIGNED_8BIT) | ||||
| WRITE_SAMPLES_FUNC(b, 1, ulaw, uint8_t, uint8_t, SOX_SAMPLE_TO_ULAW_BYTE) 
 | ||||
| WRITE_SAMPLES_FUNC(b, 1, alaw, uint8_t, uint8_t, SOX_SAMPLE_TO_ALAW_BYTE) | ||||
| WRITE_SAMPLES_FUNC(w, 2, u, uint16_t, uint16_t, SOX_SAMPLE_TO_UNSIGNED_16BIT) 
 | ||||
| WRITE_SAMPLES_FUNC(w, 2, s, int16_t, uint16_t, SOX_SAMPLE_TO_SIGNED_16BIT) | ||||
| WRITE_SAMPLES_FUNC(3, 3, u, sox_uint24_t, sox_uint24_t, SOX_SAMPLE_TO_UNSIGNED_24BIT) 
 | ||||
| WRITE_SAMPLES_FUNC(3, 3, s, sox_int24_t, sox_uint24_t, SOX_SAMPLE_TO_SIGNED_24BIT) | ||||
| WRITE_SAMPLES_FUNC(dw, 4, u, uint32_t, uint32_t, SOX_SAMPLE_TO_UNSIGNED_32BIT) 
 | ||||
| WRITE_SAMPLES_FUNC(dw, 4, s, int32_t, uint32_t, SOX_SAMPLE_TO_SIGNED_32BIT) | ||||
| WRITE_SAMPLES_FUNC(f, sizeof(float), su, float, float, SOX_SAMPLE_TO_FLOAT_32BIT) 
 | ||||
| WRITE_SAMPLES_FUNC(df, sizeof (double), su, double, double, SOX_SAMPLE_TO_FLOAT_64BIT) | ||||
| 
 | ||||
| #define GET_FORMAT(type) \ | ||||
| static ft_##type##_fn * type##_fn(sox_format_t * ft) { \
 | ||||
|   switch (ft->encoding.bits_per_sample) { \
 | ||||
|     case 8: \
 | ||||
|       switch (ft->encoding.encoding) { \
 | ||||
|         case SOX_ENCODING_SIGN2: return sox_##type##_sb_samples; \
 | ||||
|         case SOX_ENCODING_UNSIGNED: return sox_##type##_ub_samples; \
 | ||||
|         case SOX_ENCODING_ULAW: return sox_##type##_ulawb_samples; \
 | ||||
|         case SOX_ENCODING_ALAW: return sox_##type##_alawb_samples; \
 | ||||
|         default: break; } \
 | ||||
|       break; \
 | ||||
|     case 16: \
 | ||||
|       switch (ft->encoding.encoding) { \
 | ||||
|         case SOX_ENCODING_SIGN2: return sox_##type##_sw_samples; \
 | ||||
|         case SOX_ENCODING_UNSIGNED: return sox_##type##_uw_samples; \
 | ||||
|         default: break; } \
 | ||||
|       break; \
 | ||||
|     case 24: \
 | ||||
|       switch (ft->encoding.encoding) { \
 | ||||
|         case SOX_ENCODING_SIGN2:    return sox_##type##_s3_samples; \
 | ||||
|         case SOX_ENCODING_UNSIGNED: return sox_##type##_u3_samples; \
 | ||||
|         default: break; } \
 | ||||
|       break; \
 | ||||
|     case 32: \
 | ||||
|       switch (ft->encoding.encoding) { \
 | ||||
|         case SOX_ENCODING_SIGN2: return sox_##type##_sdw_samples; \
 | ||||
|         case SOX_ENCODING_UNSIGNED: return sox_##type##_udw_samples; \
 | ||||
|         case SOX_ENCODING_FLOAT: return sox_##type##_suf_samples; \
 | ||||
|         default: break; } \
 | ||||
|       break; \
 | ||||
|     case 64: \
 | ||||
|       switch (ft->encoding.encoding) { \
 | ||||
|         case SOX_ENCODING_FLOAT: return sox_##type##_sudf_samples; \
 | ||||
|         default: break; } \
 | ||||
|       break; \
 | ||||
|     default: \
 | ||||
|       lsx_fail_errno(ft, SOX_EFMT, "this handler does not support this data size"); \
 | ||||
|       return NULL; } \
 | ||||
|   lsx_fail_errno(ft, SOX_EFMT, "this encoding is not supported for this data size"); \
 | ||||
|   return NULL; } | ||||
| 
 | ||||
| typedef size_t(ft_read_fn) | ||||
|   (sox_format_t * ft, sox_sample_t * buf, size_t len); | ||||
| 
 | ||||
| GET_FORMAT(read) | ||||
| 
 | ||||
| /* Read a stream of some type into SoX's internal buffer format. */ | ||||
| size_t lsx_rawread(sox_format_t * ft, sox_sample_t * buf, size_t nsamp) | ||||
| { | ||||
|   ft_read_fn * read_buf = read_fn(ft); | ||||
| 
 | ||||
|   if (read_buf && nsamp) | ||||
|     return read_buf(ft, buf, nsamp); | ||||
|   return 0; | ||||
| } | ||||
| 
 | ||||
| typedef size_t(ft_write_fn) | ||||
|   (sox_format_t * ft, sox_sample_t const * buf, size_t len); | ||||
| 
 | ||||
| GET_FORMAT(write) | ||||
| 
 | ||||
| /* Writes SoX's internal buffer format to buffer of various data types. */ | ||||
| size_t lsx_rawwrite( | ||||
|     sox_format_t * ft, sox_sample_t const * buf, size_t nsamp) | ||||
| { | ||||
|   ft_write_fn * write_buf = write_fn(ft); | ||||
| 
 | ||||
|   if (write_buf && nsamp) | ||||
|     return write_buf(ft, buf, nsamp); | ||||
|   return 0; | ||||
| } | ||||
| @ -1,54 +0,0 @@ | ||||
| /* libSoX file formats: raw         (c) 2007-8 SoX contributors
 | ||||
|  * | ||||
|  * This library is free software; you can redistribute it and/or modify it | ||||
|  * under the terms of the GNU Lesser General Public License as published by | ||||
|  * the Free Software Foundation; either version 2.1 of the License, or (at | ||||
|  * your option) any later version. | ||||
|  * | ||||
|  * This library is distributed in the hope that it will be useful, but | ||||
|  * WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser | ||||
|  * General Public License for more details. | ||||
|  * | ||||
|  * You should have received a copy of the GNU Lesser General Public License | ||||
|  * along with this library; if not, write to the Free Software Foundation, | ||||
|  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA | ||||
|  */ | ||||
| 
 | ||||
| #define RAW_FORMAT0(id, size, flags, encoding) \ | ||||
| static int id ## _start(sox_format_t * ft) { \
 | ||||
|   return lsx_rawstart(ft, sox_true, sox_true, sox_true, SOX_ENCODING_ ## encoding, size); \
 | ||||
| } \
 | ||||
| const sox_format_handler_t *lsx_ ## id ## _format_fn(void); \
 | ||||
| const sox_format_handler_t *lsx_ ## id ## _format_fn(void) { \
 | ||||
|   static unsigned const write_encodings[] = { \
 | ||||
|     SOX_ENCODING_ ## encoding, size, 0, 0}; \
 | ||||
|   static sox_format_handler_t handler = { \
 | ||||
|     SOX_LIB_VERSION_CODE, "Raw audio", \
 | ||||
|     names, flags, \
 | ||||
|     id ## _start, lsx_rawread , NULL, \
 | ||||
|     id ## _start, lsx_rawwrite, NULL, \
 | ||||
|     NULL, write_encodings, NULL, 0 \
 | ||||
|   }; \
 | ||||
|   return &handler; \
 | ||||
| } | ||||
| 
 | ||||
| #define RAW_FORMAT(id, size, flags, encoding) \ | ||||
|   static char const *names[] = {#id, NULL}; \
 | ||||
|   RAW_FORMAT0(id, size, flags, encoding) | ||||
| 
 | ||||
| #define RAW_FORMAT1(id, alt, size, flags, encoding) \ | ||||
|   static char const *names[] = {#id, alt, NULL}; \
 | ||||
|   RAW_FORMAT0(id, size, flags, encoding) | ||||
| 
 | ||||
| #define RAW_FORMAT2(id, alt1, alt2, size, flags, encoding) \ | ||||
|   static char const *names[] = {#id, alt1, alt2, NULL}; \
 | ||||
|   RAW_FORMAT0(id, size, flags, encoding) | ||||
| 
 | ||||
| #define RAW_FORMAT3(id, alt1, alt2, alt3, size, flags, encoding) \ | ||||
|   static char const *names[] = {#id, alt1, alt2, alt3, NULL}; \
 | ||||
|   RAW_FORMAT0(id, size, flags, encoding) | ||||
| 
 | ||||
| #define RAW_FORMAT4(id, alt1, alt2, alt3, alt4, size, flags, encoding) \ | ||||
|   static char const *names[] = {#id, alt1, alt2, alt3, alt4, NULL}; \
 | ||||
|   RAW_FORMAT0(id, size, flags, encoding) | ||||
| @ -1,277 +0,0 @@ | ||||
| /* libSoX effect: stereo reverberation
 | ||||
|  * Copyright (c) 2007 robs@users.sourceforge.net | ||||
|  * Filter design based on freeverb by Jezar at Dreampoint. | ||||
|  * | ||||
|  * This library is free software; you can redistribute it and/or modify it | ||||
|  * under the terms of the GNU Lesser General Public License as published by | ||||
|  * the Free Software Foundation; either version 2.1 of the License, or (at | ||||
|  * your option) any later version. | ||||
|  * | ||||
|  * This library is distributed in the hope that it will be useful, but | ||||
|  * WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser | ||||
|  * General Public License for more details. | ||||
|  * | ||||
|  * You should have received a copy of the GNU Lesser General Public License | ||||
|  * along with this library; if not, write to the Free Software Foundation, | ||||
|  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA | ||||
|  */ | ||||
| 
 | ||||
| #include "sox_i.h" | ||||
| #include "fifo.h" | ||||
| 
 | ||||
| #define lsx_zalloc(var, n) var = lsx_calloc(n, sizeof(*var)) | ||||
| #define filter_advance(p) if (--(p)->ptr < (p)->buffer) (p)->ptr += (p)->size | ||||
| #define filter_delete(p) free((p)->buffer) | ||||
| 
 | ||||
| typedef struct { | ||||
|   size_t  size; | ||||
|   float   * buffer, * ptr; | ||||
|   float   store; | ||||
| } filter_t; | ||||
| 
 | ||||
| static float comb_process(filter_t * p,  /* gcc -O2 will inline this */ | ||||
|     float const * input, float const * feedback, float const * hf_damping) | ||||
| { | ||||
|   float output = *p->ptr; | ||||
|   p->store = output + (p->store - output) * *hf_damping; | ||||
|   *p->ptr = *input + p->store * *feedback; | ||||
|   filter_advance(p); | ||||
|   return output; | ||||
| } | ||||
| 
 | ||||
| static float allpass_process(filter_t * p,  /* gcc -O2 will inline this */ | ||||
|     float const * input) | ||||
| { | ||||
|   float output = *p->ptr; | ||||
|   *p->ptr = *input + output * .5; | ||||
|   filter_advance(p); | ||||
|   return output - *input; | ||||
| } | ||||
| 
 | ||||
| static const size_t /* Filter delay lengths in samples (44100Hz sample-rate) */ | ||||
|   comb_lengths[] = {1116, 1188, 1277, 1356, 1422, 1491, 1557, 1617}, | ||||
|   allpass_lengths[] = {225, 341, 441, 556}; | ||||
| #define stereo_adjust 12 | ||||
| 
 | ||||
| typedef struct { | ||||
|   filter_t comb   [array_length(comb_lengths)]; | ||||
|   filter_t allpass[array_length(allpass_lengths)]; | ||||
| } filter_array_t; | ||||
| 
 | ||||
| static void filter_array_create(filter_array_t * p, double rate, | ||||
|     double scale, double offset) | ||||
| { | ||||
|   size_t i; | ||||
|   double r = rate * (1 / 44100.); /* Compensate for actual sample-rate */ | ||||
| 
 | ||||
|   for (i = 0; i < array_length(comb_lengths); ++i, offset = -offset) | ||||
|   { | ||||
|     filter_t * pcomb = &p->comb[i]; | ||||
|     pcomb->size = (size_t)(scale * r * (comb_lengths[i] + stereo_adjust * offset) + .5); | ||||
|     pcomb->ptr = lsx_zalloc(pcomb->buffer, pcomb->size); | ||||
|   } | ||||
|   for (i = 0; i < array_length(allpass_lengths); ++i, offset = -offset) | ||||
|   { | ||||
|     filter_t * pallpass = &p->allpass[i]; | ||||
|     pallpass->size = (size_t)(r * (allpass_lengths[i] + stereo_adjust * offset) + .5); | ||||
|     pallpass->ptr = lsx_zalloc(pallpass->buffer, pallpass->size); | ||||
|   } | ||||
| } | ||||
| 
 | ||||
| static void filter_array_process(filter_array_t * p, | ||||
|     size_t length, float const * input, float * output, | ||||
|     float const * feedback, float const * hf_damping, float const * gain) | ||||
| { | ||||
|   while (length--) { | ||||
|     float out = 0, in = *input++; | ||||
| 
 | ||||
|     size_t i = array_length(comb_lengths) - 1; | ||||
|     do out += comb_process(p->comb + i, &in, feedback, hf_damping); | ||||
|     while (i--); | ||||
| 
 | ||||
|     i = array_length(allpass_lengths) - 1; | ||||
|     do out = allpass_process(p->allpass + i, &out); | ||||
|     while (i--); | ||||
| 
 | ||||
|     *output++ = out * *gain; | ||||
|   } | ||||
| } | ||||
| 
 | ||||
| static void filter_array_delete(filter_array_t * p) | ||||
| { | ||||
|   size_t i; | ||||
| 
 | ||||
|   for (i = 0; i < array_length(allpass_lengths); ++i) | ||||
|     filter_delete(&p->allpass[i]); | ||||
|   for (i = 0; i < array_length(comb_lengths); ++i) | ||||
|     filter_delete(&p->comb[i]); | ||||
| } | ||||
| 
 | ||||
| typedef struct { | ||||
|   float feedback; | ||||
|   float hf_damping; | ||||
|   float gain; | ||||
|   fifo_t input_fifo; | ||||
|   filter_array_t chan[2]; | ||||
|   float * out[2]; | ||||
| } reverb_t; | ||||
| 
 | ||||
| static void reverb_create(reverb_t * p, double sample_rate_Hz, | ||||
|     double wet_gain_dB, | ||||
|     double room_scale,     /* % */ | ||||
|     double reverberance,   /* % */ | ||||
|     double hf_damping,     /* % */ | ||||
|     double pre_delay_ms, | ||||
|     double stereo_depth, | ||||
|     size_t buffer_size, | ||||
|     float * * out) | ||||
| { | ||||
|   size_t i, delay = pre_delay_ms / 1000 * sample_rate_Hz + .5; | ||||
|   double scale = room_scale / 100 * .9 + .1; | ||||
|   double depth = stereo_depth / 100; | ||||
|   double a =  -1 /  log(1 - /**/.3 /**/);           /* Set minimum feedback */ | ||||
|   double b = 100 / (log(1 - /**/.98/**/) * a + 1);  /* Set maximum feedback */ | ||||
| 
 | ||||
|   memset(p, 0, sizeof(*p)); | ||||
|   p->feedback = 1 - exp((reverberance - b) / (a * b)); | ||||
|   p->hf_damping = hf_damping / 100 * .3 + .2; | ||||
|   p->gain = dB_to_linear(wet_gain_dB) * .015; | ||||
|   fifo_create(&p->input_fifo, sizeof(float)); | ||||
|   memset(fifo_write(&p->input_fifo, delay, 0), 0, delay * sizeof(float)); | ||||
|   for (i = 0; i <= ceil(depth); ++i) { | ||||
|     filter_array_create(p->chan + i, sample_rate_Hz, scale, i * depth); | ||||
|     out[i] = lsx_zalloc(p->out[i], buffer_size); | ||||
|   } | ||||
| } | ||||
| 
 | ||||
| static void reverb_process(reverb_t * p, size_t length) | ||||
| { | ||||
|   size_t i; | ||||
|   for (i = 0; i < 2 && p->out[i]; ++i) | ||||
|     filter_array_process(p->chan + i, length, (float *) fifo_read_ptr(&p->input_fifo), p->out[i], &p->feedback, &p->hf_damping, &p->gain); | ||||
|   fifo_read(&p->input_fifo, length, NULL); | ||||
| } | ||||
| 
 | ||||
| static void reverb_delete(reverb_t * p) | ||||
| { | ||||
|   size_t i; | ||||
|   for (i = 0; i < 2 && p->out[i]; ++i) { | ||||
|     free(p->out[i]); | ||||
|     filter_array_delete(p->chan + i); | ||||
|   } | ||||
|   fifo_delete(&p->input_fifo); | ||||
| } | ||||
| 
 | ||||
| /*------------------------------- SoX Wrapper --------------------------------*/ | ||||
| 
 | ||||
| typedef struct { | ||||
|   double reverberance, hf_damping, pre_delay_ms; | ||||
|   double stereo_depth, wet_gain_dB, room_scale; | ||||
|   sox_bool wet_only; | ||||
| 
 | ||||
|   size_t ichannels, ochannels; | ||||
|   struct { | ||||
|     reverb_t reverb; | ||||
|     float * dry, * wet[2]; | ||||
|   } chan[2]; | ||||
| } priv_t; | ||||
| 
 | ||||
| static int getopts(sox_effect_t * effp, int argc, char **argv) | ||||
| { | ||||
|   priv_t * p = (priv_t *)effp->priv; | ||||
|   p->reverberance = p->hf_damping = 50; /* Set non-zero defaults */ | ||||
|   p->stereo_depth = p->room_scale = 100; | ||||
| 
 | ||||
|   --argc, ++argv; | ||||
|   p->wet_only = argc && (!strcmp(*argv, "-w") || !strcmp(*argv, "--wet-only")) | ||||
|     && (--argc, ++argv, sox_true); | ||||
|   do {  /* break-able block */ | ||||
|     NUMERIC_PARAMETER(reverberance, 0, 100) | ||||
|     NUMERIC_PARAMETER(hf_damping, 0, 100) | ||||
|     NUMERIC_PARAMETER(room_scale, 0, 100) | ||||
|     NUMERIC_PARAMETER(stereo_depth, 0, 100) | ||||
|     NUMERIC_PARAMETER(pre_delay_ms, 0, 500) | ||||
|     NUMERIC_PARAMETER(wet_gain_dB, -10, 10) | ||||
|   } while (0); | ||||
| 
 | ||||
|   return argc ? lsx_usage(effp) : SOX_SUCCESS; | ||||
| } | ||||
| 
 | ||||
| static int start(sox_effect_t * effp) | ||||
| { | ||||
|   priv_t * p = (priv_t *)effp->priv; | ||||
|   size_t i; | ||||
| 
 | ||||
|   p->ichannels = p->ochannels = 1; | ||||
|   effp->out_signal.rate = effp->in_signal.rate; | ||||
|   if (effp->in_signal.channels > 2 && p->stereo_depth) { | ||||
|     lsx_warn("stereo-depth not applicable with >2 channels"); | ||||
|     p->stereo_depth = 0; | ||||
|   } | ||||
|   if (effp->in_signal.channels == 1 && p->stereo_depth) | ||||
|     effp->out_signal.channels = p->ochannels = 2; | ||||
|   else effp->out_signal.channels = effp->in_signal.channels; | ||||
|   if (effp->in_signal.channels == 2 && p->stereo_depth) | ||||
|     p->ichannels = p->ochannels = 2; | ||||
|   else effp->flows = effp->in_signal.channels; | ||||
|   for (i = 0; i < p->ichannels; ++i) reverb_create( | ||||
|     &p->chan[i].reverb, effp->in_signal.rate, p->wet_gain_dB, p->room_scale, | ||||
|     p->reverberance, p->hf_damping, p->pre_delay_ms, p->stereo_depth, | ||||
|     effp->global_info->global_info->bufsiz / p->ochannels, p->chan[i].wet); | ||||
| 
 | ||||
|   if (effp->in_signal.mult) | ||||
|     *effp->in_signal.mult /= !p->wet_only + 2 * dB_to_linear(max(0,p->wet_gain_dB)); | ||||
|   return SOX_SUCCESS; | ||||
| } | ||||
| 
 | ||||
| static int flow(sox_effect_t * effp, const sox_sample_t * ibuf, | ||||
|                 sox_sample_t * obuf, size_t * isamp, size_t * osamp) | ||||
| { | ||||
|   priv_t * p = (priv_t *)effp->priv; | ||||
|   size_t c, i, w, len = min(*isamp / p->ichannels, *osamp / p->ochannels); | ||||
|   SOX_SAMPLE_LOCALS; | ||||
| 
 | ||||
|   *isamp = len * p->ichannels, *osamp = len * p->ochannels; | ||||
|   for (c = 0; c < p->ichannels; ++c) | ||||
|     p->chan[c].dry = fifo_write(&p->chan[c].reverb.input_fifo, len, 0); | ||||
|   for (i = 0; i < len; ++i) for (c = 0; c < p->ichannels; ++c) | ||||
|     p->chan[c].dry[i] = SOX_SAMPLE_TO_FLOAT_32BIT(*ibuf++, effp->clips); | ||||
|   for (c = 0; c < p->ichannels; ++c) | ||||
|     reverb_process(&p->chan[c].reverb, len); | ||||
|   if (p->ichannels == 2) for (i = 0; i < len; ++i) for (w = 0; w < 2; ++w) { | ||||
|     float out = (1 - p->wet_only) * p->chan[w].dry[i] + | ||||
|       .5 * (p->chan[0].wet[w][i] + p->chan[1].wet[w][i]); | ||||
|     *obuf++ = SOX_FLOAT_32BIT_TO_SAMPLE(out, effp->clips); | ||||
|   } | ||||
|   else for (i = 0; i < len; ++i) for (w = 0; w < p->ochannels; ++w) { | ||||
|     float out = (1 - p->wet_only) * p->chan[0].dry[i] + p->chan[0].wet[w][i]; | ||||
|     *obuf++ = SOX_FLOAT_32BIT_TO_SAMPLE(out, effp->clips); | ||||
|   } | ||||
|   return SOX_SUCCESS; | ||||
| } | ||||
| 
 | ||||
| static int stop(sox_effect_t * effp) | ||||
| { | ||||
|   priv_t * p = (priv_t *)effp->priv; | ||||
|   size_t i; | ||||
|   for (i = 0; i < p->ichannels; ++i) | ||||
|     reverb_delete(&p->chan[i].reverb); | ||||
|   return SOX_SUCCESS; | ||||
| } | ||||
| 
 | ||||
| sox_effect_handler_t const *lsx_reverb_effect_fn(void) | ||||
| { | ||||
|   static sox_effect_handler_t handler = {"reverb", | ||||
|     "[-w|--wet-only]" | ||||
|     " [reverberance (50%)" | ||||
|     " [HF-damping (50%)" | ||||
|     " [room-scale (100%)" | ||||
|     " [stereo-depth (100%)" | ||||
|     " [pre-delay (0ms)" | ||||
|     " [wet-gain (0dB)" | ||||
|     "]]]]]]", | ||||
|     SOX_EFF_MCHAN, getopts, start, flow, NULL, stop, NULL, sizeof(priv_t) | ||||
|   }; | ||||
|   return &handler; | ||||
| } | ||||
									
										
											File diff suppressed because it is too large
											Load Diff
										
									
								
							
						
									
										
											File diff suppressed because it is too large
											Load Diff
										
									
								
							
						| @ -1,416 +0,0 @@ | ||||
| /* libSoX Internal header
 | ||||
|  * | ||||
|  *   This file is meant for libSoX internal use only | ||||
|  * | ||||
|  * Copyright 2001-2012 Chris Bagwell and SoX Contributors | ||||
|  * | ||||
|  * This source code is freely redistributable and may be used for | ||||
|  * any purpose.  This copyright notice must be maintained. | ||||
|  * Chris Bagwell And SoX Contributors are not responsible for | ||||
|  * the consequences of using this software. | ||||
|  */ | ||||
| 
 | ||||
| #ifndef SOX_I_H | ||||
| #define SOX_I_H | ||||
| 
 | ||||
| #include "soxomp.h"  /* Note: soxomp.h includes soxconfig.h */ | ||||
| #include "sox.h" | ||||
| 
 | ||||
| #if defined HAVE_FMEMOPEN | ||||
| #define _GNU_SOURCE | ||||
| #endif | ||||
| 
 | ||||
| #include <errno.h> | ||||
| #include <stdio.h> | ||||
| #include <stdlib.h> | ||||
| 
 | ||||
| #include "util.h" | ||||
| 
 | ||||
| #if defined(LSX_EFF_ALIAS) | ||||
| #undef lsx_debug | ||||
| #undef lsx_fail | ||||
| #undef lsx_report | ||||
| #undef lsx_warn | ||||
| #define lsx_debug sox_globals.subsystem=effp->handler.name,lsx_debug_impl | ||||
| #define lsx_fail sox_globals.subsystem=effp->handler.name,lsx_fail_impl | ||||
| #define lsx_report sox_globals.subsystem=effp->handler.name,lsx_report_impl | ||||
| #define lsx_warn sox_globals.subsystem=effp->handler.name,lsx_warn_impl | ||||
| #endif | ||||
| 
 | ||||
| #define RANQD1 ranqd1(sox_globals.ranqd1) | ||||
| #define DRANQD1 dranqd1(sox_globals.ranqd1) | ||||
| 
 | ||||
| typedef enum {SOX_SHORT, SOX_INT, SOX_FLOAT, SOX_DOUBLE} sox_data_t; | ||||
| typedef enum {SOX_WAVE_SINE, SOX_WAVE_TRIANGLE} lsx_wave_t; | ||||
| lsx_enum_item const * lsx_get_wave_enum(void); | ||||
| 
 | ||||
| /* Define fseeko and ftello for platforms lacking them */ | ||||
| #ifndef HAVE_FSEEKO | ||||
| #define fseeko fseek | ||||
| #define ftello ftell | ||||
| #endif | ||||
| 
 | ||||
| #ifdef _FILE_OFFSET_BITS | ||||
| assert_static(sizeof(off_t) == _FILE_OFFSET_BITS >> 3, OFF_T_BUILD_PROBLEM); | ||||
| #endif | ||||
| 
 | ||||
| FILE * lsx_tmpfile(void); | ||||
| 
 | ||||
| void lsx_debug_more_impl(char const * fmt, ...) LSX_PRINTF12; | ||||
| void lsx_debug_most_impl(char const * fmt, ...) LSX_PRINTF12; | ||||
| 
 | ||||
| #define lsx_debug_more sox_get_globals()->subsystem=__FILE__,lsx_debug_more_impl | ||||
| #define lsx_debug_most sox_get_globals()->subsystem=__FILE__,lsx_debug_most_impl | ||||
| 
 | ||||
| /* Digitise one cycle of a wave and store it as
 | ||||
|  * a table of samples of a specified data-type. | ||||
|  */ | ||||
| void lsx_generate_wave_table( | ||||
|     lsx_wave_t wave_type, | ||||
|     sox_data_t data_type, | ||||
|     void * table,       /* Really of type indicated by data_type. */ | ||||
|     size_t table_size,  /* Number of points on the x-axis. */ | ||||
|     double min,         /* Minimum value on the y-axis. (e.g. -1) */ | ||||
|     double max,         /* Maximum value on the y-axis. (e.g. +1) */ | ||||
|     double phase);      /* Phase at 1st point; 0..2pi. (e.g. pi/2 for cosine) */ | ||||
| char const * lsx_parsesamples(sox_rate_t rate, const char *str, uint64_t *samples, int def); | ||||
| char const * lsx_parseposition(sox_rate_t rate, const char *str, uint64_t *samples, uint64_t latest, uint64_t end, int def); | ||||
| int lsx_parse_note(char const * text, char * * end_ptr); | ||||
| double lsx_parse_frequency_k(char const * text, char * * end_ptr, int key); | ||||
| #define lsx_parse_frequency(a, b) lsx_parse_frequency_k(a, b, INT_MAX) | ||||
| FILE * lsx_open_input_file(sox_effect_t * effp, char const * filename, sox_bool text_mode); | ||||
| 
 | ||||
| void lsx_prepare_spline3(double const * x, double const * y, int n, | ||||
|     double start_1d, double end_1d, double * y_2d); | ||||
| double lsx_spline3(double const * x, double const * y, double const * y_2d, | ||||
|     int n, double x1); | ||||
| 
 | ||||
| double lsx_bessel_I_0(double x); | ||||
| int lsx_set_dft_length(int num_taps); | ||||
| void init_fft_cache(void); | ||||
| void clear_fft_cache(void); | ||||
| #define lsx_is_power_of_2(x) !(x < 2 || (x & (x - 1))) | ||||
| void lsx_safe_rdft(int len, int type, double * d); | ||||
| void lsx_safe_cdft(int len, int type, double * d); | ||||
| void lsx_power_spectrum(int n, double const * in, double * out); | ||||
| void lsx_power_spectrum_f(int n, float const * in, float * out); | ||||
| void lsx_apply_hann_f(float h[], const int num_points); | ||||
| void lsx_apply_hann(double h[], const int num_points); | ||||
| void lsx_apply_hamming(double h[], const int num_points); | ||||
| void lsx_apply_bartlett(double h[], const int num_points); | ||||
| void lsx_apply_blackman(double h[], const int num_points, double alpha); | ||||
| void lsx_apply_blackman_nutall(double h[], const int num_points); | ||||
| double lsx_kaiser_beta(double att, double tr_bw); | ||||
| void lsx_apply_kaiser(double h[], const int num_points, double beta); | ||||
| void lsx_apply_dolph(double h[], const int num_points, double att); | ||||
| double * lsx_make_lpf(int num_taps, double Fc, double beta, double rho, | ||||
|     double scale, sox_bool dc_norm); | ||||
| void lsx_kaiser_params(double att, double Fc, double tr_bw, double * beta, int * num_taps); | ||||
| double * lsx_design_lpf( | ||||
|     double Fp,      /* End of pass-band */ | ||||
|     double Fs,      /* Start of stop-band */ | ||||
|     double Fn,      /* Nyquist freq; e.g. 0.5, 1, PI; < 0: dummy run */ | ||||
|     double att,     /* Stop-band attenuation in dB */ | ||||
|     int * num_taps, /* 0: value will be estimated */ | ||||
|     int k,          /* >0: number of phases; <0: num_taps ≡ 1 (mod -k) */ | ||||
|     double beta);   /* <0: value will be estimated */ | ||||
| void lsx_fir_to_phase(double * * h, int * len, | ||||
|     int * post_len, double phase0); | ||||
| void lsx_plot_fir(double * h, int num_points, sox_rate_t rate, sox_plot_t type, char const * title, double y1, double y2); | ||||
| void lsx_save_samples(sox_sample_t * const dest, double const * const src, | ||||
|     size_t const n, sox_uint64_t * const clips); | ||||
| void lsx_load_samples(double * const dest, sox_sample_t const * const src, | ||||
|     size_t const n); | ||||
| 
 | ||||
| #ifdef HAVE_BYTESWAP_H | ||||
| #include <byteswap.h> | ||||
| #define lsx_swapw(x) bswap_16(x) | ||||
| #define lsx_swapdw(x) bswap_32(x) | ||||
| #elif defined(_MSC_VER) | ||||
| #define lsx_swapw(x) _byteswap_ushort(x) | ||||
| #define lsx_swapdw(x) _byteswap_ulong(x) | ||||
| #else | ||||
| #define lsx_swapw(uw) (((uw >> 8) | (uw << 8)) & 0xffff) | ||||
| #define lsx_swapdw(udw) ((udw >> 24) | ((udw >> 8) & 0xff00) | ((udw << 8) & 0xff0000) | (udw << 24)) | ||||
| #endif | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| /*------------------------ Implemented in libsoxio.c -------------------------*/ | ||||
| 
 | ||||
| /* Read and write basic data types from "ft" stream. */ | ||||
| size_t lsx_readbuf(sox_format_t * ft, void *buf, size_t len); | ||||
| int lsx_skipbytes(sox_format_t * ft, size_t n); | ||||
| int lsx_padbytes(sox_format_t * ft, size_t n); | ||||
| size_t lsx_writebuf(sox_format_t * ft, void const *buf, size_t len); | ||||
| int lsx_reads(sox_format_t * ft, char *c, size_t len); | ||||
| int lsx_writes(sox_format_t * ft, char const * c); | ||||
| void lsx_set_signal_defaults(sox_format_t * ft); | ||||
| #define lsx_writechars(ft, chars, len) (lsx_writebuf(ft, chars, len) == len? SOX_SUCCESS : SOX_EOF) | ||||
| 
 | ||||
| size_t lsx_read_3_buf(sox_format_t * ft, sox_uint24_t *buf, size_t len); | ||||
| size_t lsx_read_b_buf(sox_format_t * ft, uint8_t *buf, size_t len); | ||||
| size_t lsx_read_df_buf(sox_format_t * ft, double *buf, size_t len); | ||||
| size_t lsx_read_dw_buf(sox_format_t * ft, uint32_t *buf, size_t len); | ||||
| size_t lsx_read_qw_buf(sox_format_t * ft, uint64_t *buf, size_t len); | ||||
| size_t lsx_read_f_buf(sox_format_t * ft, float *buf, size_t len); | ||||
| size_t lsx_read_w_buf(sox_format_t * ft, uint16_t *buf, size_t len); | ||||
| 
 | ||||
| size_t lsx_write_3_buf(sox_format_t * ft, sox_uint24_t *buf, size_t len); | ||||
| size_t lsx_write_b_buf(sox_format_t * ft, uint8_t *buf, size_t len); | ||||
| size_t lsx_write_df_buf(sox_format_t * ft, double *buf, size_t len); | ||||
| size_t lsx_write_dw_buf(sox_format_t * ft, uint32_t *buf, size_t len); | ||||
| size_t lsx_write_qw_buf(sox_format_t * ft, uint64_t *buf, size_t len); | ||||
| size_t lsx_write_f_buf(sox_format_t * ft, float *buf, size_t len); | ||||
| size_t lsx_write_w_buf(sox_format_t * ft, uint16_t *buf, size_t len); | ||||
| 
 | ||||
| int lsx_read3(sox_format_t * ft, sox_uint24_t * u3); | ||||
| int lsx_readb(sox_format_t * ft, uint8_t * ub); | ||||
| int lsx_readchars(sox_format_t * ft, char * chars, size_t len); | ||||
| int lsx_readdf(sox_format_t * ft, double * d); | ||||
| int lsx_readdw(sox_format_t * ft, uint32_t * udw); | ||||
| int lsx_readqw(sox_format_t * ft, uint64_t * udw); | ||||
| int lsx_readf(sox_format_t * ft, float * f); | ||||
| int lsx_readw(sox_format_t * ft, uint16_t * uw); | ||||
| 
 | ||||
| #if 1 /* FIXME: use defines */ | ||||
| UNUSED static int lsx_readsb(sox_format_t * ft, int8_t * sb) | ||||
| {return lsx_readb(ft, (uint8_t *)sb);} | ||||
| UNUSED static int lsx_readsw(sox_format_t * ft, int16_t * sw) | ||||
| {return lsx_readw(ft, (uint16_t *)sw);} | ||||
| #else | ||||
| #define lsx_readsb(ft, sb) lsx_readb(ft, (uint8_t *)sb) | ||||
| #define lsx_readsw(ft, sw) lsx_readb(ft, (uint16_t *)sw) | ||||
| #endif | ||||
| 
 | ||||
| int lsx_read_fields(sox_format_t *ft, uint32_t *len,  const char *spec, ...); | ||||
| 
 | ||||
| int lsx_write3(sox_format_t * ft, unsigned u3); | ||||
| int lsx_writeb(sox_format_t * ft, unsigned ub); | ||||
| int lsx_writedf(sox_format_t * ft, double d); | ||||
| int lsx_writedw(sox_format_t * ft, unsigned udw); | ||||
| int lsx_writeqw(sox_format_t * ft, uint64_t uqw); | ||||
| int lsx_writef(sox_format_t * ft, double f); | ||||
| int lsx_writew(sox_format_t * ft, unsigned uw); | ||||
| 
 | ||||
| int lsx_writesb(sox_format_t * ft, signed); | ||||
| int lsx_writesw(sox_format_t * ft, signed); | ||||
| 
 | ||||
| int lsx_eof(sox_format_t * ft); | ||||
| int lsx_error(sox_format_t * ft); | ||||
| int lsx_flush(sox_format_t * ft); | ||||
| int lsx_seeki(sox_format_t * ft, off_t offset, int whence); | ||||
| int lsx_unreadb(sox_format_t * ft, unsigned ub); | ||||
| /* uint64_t lsx_filelength(sox_format_t * ft); Temporarily Moved to sox.h. */ | ||||
| off_t lsx_tell(sox_format_t * ft); | ||||
| void lsx_clearerr(sox_format_t * ft); | ||||
| void lsx_rewind(sox_format_t * ft); | ||||
| 
 | ||||
| int lsx_offset_seek(sox_format_t * ft, off_t byte_offset, off_t to_sample); | ||||
| 
 | ||||
| void lsx_fail_errno(sox_format_t *, int, const char *, ...) | ||||
| #ifdef __GNUC__ | ||||
| __attribute__ ((format (printf, 3, 4))); | ||||
| #else | ||||
| ; | ||||
| #endif | ||||
| 
 | ||||
| typedef struct sox_formats_globals { /* Global parameters (for formats) */ | ||||
|   sox_globals_t * global_info; | ||||
| } sox_formats_globals; | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| /*------------------------------ File Handlers -------------------------------*/ | ||||
| 
 | ||||
| int lsx_check_read_params(sox_format_t * ft, unsigned channels, | ||||
|     sox_rate_t rate, sox_encoding_t encoding, unsigned bits_per_sample, | ||||
|     uint64_t num_samples, sox_bool check_length); | ||||
| #define LSX_FORMAT_HANDLER(name) \ | ||||
| sox_format_handler_t const * lsx_##name##_format_fn(void); \
 | ||||
| sox_format_handler_t const * lsx_##name##_format_fn(void) | ||||
| #define div_bits(size, bits) ((uint64_t)(size) * 8 / bits) | ||||
| 
 | ||||
| /* Raw I/O */ | ||||
| int lsx_rawstartread(sox_format_t * ft); | ||||
| size_t lsx_rawread(sox_format_t * ft, sox_sample_t *buf, size_t nsamp); | ||||
| int lsx_rawstopread(sox_format_t * ft); | ||||
| int lsx_rawstartwrite(sox_format_t * ft); | ||||
| size_t lsx_rawwrite(sox_format_t * ft, const sox_sample_t *buf, size_t nsamp); | ||||
| int lsx_rawseek(sox_format_t * ft, uint64_t offset); | ||||
| int lsx_rawstart(sox_format_t * ft, sox_bool default_rate, sox_bool default_channels, sox_bool default_length, sox_encoding_t encoding, unsigned bits_per_sample); | ||||
| #define lsx_rawstartread(ft) lsx_rawstart(ft, sox_false, sox_false, sox_false, SOX_ENCODING_UNKNOWN, 0) | ||||
| #define lsx_rawstartwrite lsx_rawstartread | ||||
| #define lsx_rawstopread NULL | ||||
| #define lsx_rawstopwrite NULL | ||||
| 
 | ||||
| extern sox_format_handler_t const * lsx_sndfile_format_fn(void); | ||||
| 
 | ||||
| char * lsx_cat_comments(sox_comments_t comments); | ||||
| 
 | ||||
| /*--------------------------------- Effects ----------------------------------*/ | ||||
| 
 | ||||
| int lsx_flow_copy(sox_effect_t * effp, const sox_sample_t * ibuf, | ||||
|     sox_sample_t * obuf, size_t * isamp, size_t * osamp); | ||||
| int lsx_usage(sox_effect_t * effp); | ||||
| char * lsx_usage_lines(char * * usage, char const * const * lines, size_t n); | ||||
| #define EFFECT(f) extern sox_effect_handler_t const * lsx_##f##_effect_fn(void); | ||||
| #include "effects.h" | ||||
| #undef EFFECT | ||||
| 
 | ||||
| #define NUMERIC_PARAMETER(name, min, max) { \ | ||||
|   char * end_ptr; \
 | ||||
|   double d; \
 | ||||
|   if (argc == 0) break; \
 | ||||
|   d = strtod(*argv, &end_ptr); \
 | ||||
|   if (end_ptr != *argv) { \
 | ||||
|     if (d < min || d > max || *end_ptr != '\0') {\
 | ||||
|       lsx_fail("parameter `%s' must be between %g and %g", #name, (double)min, (double)max); \
 | ||||
|       return lsx_usage(effp); \
 | ||||
|     } \
 | ||||
|     p->name = d; \
 | ||||
|     --argc, ++argv; \
 | ||||
|   } \
 | ||||
| } | ||||
| 
 | ||||
| #define TEXTUAL_PARAMETER(name, enum_table) { \ | ||||
|   lsx_enum_item const * e; \
 | ||||
|   if (argc == 0) break; \
 | ||||
|   e = lsx_find_enum_text(*argv, enum_table, 0); \
 | ||||
|   if (e != NULL) { \
 | ||||
|     p->name = e->value; \
 | ||||
|     --argc, ++argv; \
 | ||||
|   } \
 | ||||
| } | ||||
| 
 | ||||
| #define GETOPT_LOCAL_NUMERIC(state, ch, name, min, max) case ch:{ \ | ||||
|   char * end_ptr; \
 | ||||
|   double d = strtod(state.arg, &end_ptr); \
 | ||||
|   if (end_ptr == state.arg || d < min || d > max || *end_ptr != '\0') {\
 | ||||
|     lsx_fail("parameter `%s' must be between %g and %g", #name, (double)min, (double)max); \
 | ||||
|     return lsx_usage(effp); \
 | ||||
|   } \
 | ||||
|   name = d; \
 | ||||
|   break; \
 | ||||
| } | ||||
| #define GETOPT_NUMERIC(state, ch, name, min, max) GETOPT_LOCAL_NUMERIC(state, ch, p->name, min, max) | ||||
| 
 | ||||
| int lsx_effect_set_imin(sox_effect_t * effp, size_t imin); | ||||
| 
 | ||||
| int lsx_effects_init(void); | ||||
| int lsx_effects_quit(void); | ||||
| 
 | ||||
| /*--------------------------------- Dynamic Library ----------------------------------*/ | ||||
| 
 | ||||
| #if defined(HAVE_LIBLTDL) | ||||
|     #include <ltdl.h> | ||||
|     typedef lt_dlhandle lsx_dlhandle; | ||||
| #else | ||||
|     struct lsx_dlhandle_tag; | ||||
|     typedef struct lsx_dlhandle_tag *lsx_dlhandle; | ||||
| #endif | ||||
| 
 | ||||
| typedef void (*lsx_dlptr)(void); | ||||
| 
 | ||||
| typedef struct lsx_dlfunction_info | ||||
| { | ||||
|     const char* name; | ||||
|     lsx_dlptr static_func; | ||||
|     lsx_dlptr stub_func; | ||||
| } lsx_dlfunction_info; | ||||
| 
 | ||||
| int lsx_open_dllibrary( | ||||
|     int show_error_on_failure, | ||||
|     const char* library_description, | ||||
|     const char * const library_names[], | ||||
|     const lsx_dlfunction_info func_infos[], | ||||
|     lsx_dlptr selected_funcs[], | ||||
|     lsx_dlhandle* pdl); | ||||
| 
 | ||||
| void lsx_close_dllibrary( | ||||
|     lsx_dlhandle dl); | ||||
| 
 | ||||
| #define LSX_DLENTRIES_APPLY__(entries, f, x) entries(f, x) | ||||
| 
 | ||||
| #define LSX_DLENTRY_TO_PTR__(unused, func_return, func_name, func_args, static_func, stub_func, func_ptr) \ | ||||
|     func_return (*func_ptr) func_args; | ||||
| 
 | ||||
| #define LSX_DLENTRIES_TO_FUNCTIONS__(unused, func_return, func_name, func_args, static_func, stub_func, func_ptr) \ | ||||
|     func_return func_name func_args; | ||||
| 
 | ||||
| /* LSX_DLENTRIES_TO_PTRS: Given an ENTRIES macro and the name of the dlhandle
 | ||||
|    variable, declares the corresponding function pointer variables and the | ||||
|    dlhandle variable. */ | ||||
| #define LSX_DLENTRIES_TO_PTRS(entries, dlhandle) \ | ||||
|     LSX_DLENTRIES_APPLY__(entries, LSX_DLENTRY_TO_PTR__, 0) \
 | ||||
|     lsx_dlhandle dlhandle | ||||
| 
 | ||||
| /* LSX_DLENTRIES_TO_FUNCTIONS: Given an ENTRIES macro, declares the corresponding
 | ||||
|    functions. */ | ||||
| #define LSX_DLENTRIES_TO_FUNCTIONS(entries) \ | ||||
|     LSX_DLENTRIES_APPLY__(entries, LSX_DLENTRIES_TO_FUNCTIONS__, 0) | ||||
| 
 | ||||
| #define LSX_DLLIBRARY_OPEN1__(unused, func_return, func_name, func_args, static_func, stub_func, func_ptr) \ | ||||
|     { #func_name, (lsx_dlptr)(static_func), (lsx_dlptr)(stub_func) }, | ||||
| 
 | ||||
| #define LSX_DLLIBRARY_OPEN2__(ptr_container, func_return, func_name, func_args, static_func, stub_func, func_ptr) \ | ||||
|     (ptr_container)->func_ptr = (func_return (*)func_args)lsx_dlfunction_open_library_funcs[lsx_dlfunction_open_library_index++]; | ||||
| 
 | ||||
| /* LSX_DLLIBRARY_OPEN: Input an ENTRIES macro, the library's description,
 | ||||
|    a null-terminated list of library names (i.e. { "libmp3-0", "libmp3", NULL }), | ||||
|    the name of the dlhandle variable, the name of the structure that contains | ||||
|    the function pointer and dlhandle variables, and the name of the variable in | ||||
|    which the result of the lsx_open_dllibrary call should be stored. This will | ||||
|    call lsx_open_dllibrary and copy the resulting function pointers into the | ||||
|    structure members. If the library cannot be opened, show a failure message. */ | ||||
| #define LSX_DLLIBRARY_OPEN(ptr_container, dlhandle, entries, library_description, library_names, return_var) \ | ||||
|     LSX_DLLIBRARY_TRYOPEN(1, ptr_container, dlhandle, entries, library_description, library_names, return_var) | ||||
| 
 | ||||
| /* LSX_DLLIBRARY_TRYOPEN: Input an ENTRIES macro, the library's description,
 | ||||
|    a null-terminated list of library names (i.e. { "libmp3-0", "libmp3", NULL }), | ||||
|    the name of the dlhandle variable, the name of the structure that contains | ||||
|    the function pointer and dlhandle variables, and the name of the variable in | ||||
|    which the result of the lsx_open_dllibrary call should be stored. This will | ||||
|    call lsx_open_dllibrary and copy the resulting function pointers into the | ||||
|    structure members. If the library cannot be opened, show a report or a failure | ||||
|    message, depending on whether error_on_failure is non-zero. */ | ||||
| #define LSX_DLLIBRARY_TRYOPEN(error_on_failure, ptr_container, dlhandle, entries, library_description, library_names, return_var) \ | ||||
|     do { \
 | ||||
|       lsx_dlfunction_info lsx_dlfunction_open_library_infos[] = { \
 | ||||
|         LSX_DLENTRIES_APPLY__(entries, LSX_DLLIBRARY_OPEN1__, 0) \
 | ||||
|         {NULL,NULL,NULL} }; \
 | ||||
|       int lsx_dlfunction_open_library_index = 0; \
 | ||||
|       lsx_dlptr lsx_dlfunction_open_library_funcs[sizeof(lsx_dlfunction_open_library_infos)/sizeof(lsx_dlfunction_open_library_infos[0])]; \
 | ||||
|       (return_var) = lsx_open_dllibrary((error_on_failure), (library_description), (library_names), lsx_dlfunction_open_library_infos, lsx_dlfunction_open_library_funcs, &(ptr_container)->dlhandle); \
 | ||||
|       LSX_DLENTRIES_APPLY__(entries, LSX_DLLIBRARY_OPEN2__, ptr_container) \
 | ||||
|     } while(0) | ||||
| 
 | ||||
| #define LSX_DLLIBRARY_CLOSE(ptr_container, dlhandle) \ | ||||
|     lsx_close_dllibrary((ptr_container)->dlhandle) | ||||
| 
 | ||||
|   /* LSX_DLENTRY_STATIC: For use in creating an ENTRIES macro. func is
 | ||||
|      expected to be available at link time. If not present, link will fail. */ | ||||
| #define LSX_DLENTRY_STATIC(f,x, ret, func, args)  f(x, ret, func, args, func, NULL, func) | ||||
| 
 | ||||
|   /* LSX_DLENTRY_DYNAMIC: For use in creating an ENTRIES macro. func need
 | ||||
|      not be available at link time (and if present, the link time version will | ||||
|      not be used). func will be loaded via dlsym. If this function is not | ||||
|      found in the shared library, the shared library will not be used. */ | ||||
| #define LSX_DLENTRY_DYNAMIC(f,x, ret, func, args) f(x, ret, func, args, NULL, NULL, func) | ||||
| 
 | ||||
|   /* LSX_DLENTRY_STUB: For use in creating an ENTRIES macro. func need not
 | ||||
|      be available at link time (and if present, the link time version will not | ||||
|      be used). If using DL_LAME, the func may be loaded via dlopen/dlsym, but | ||||
|      if not found, the shared library will still be used if all of the | ||||
|      non-stub functions are found. If the function is not found via dlsym (or | ||||
|      if we are not loading any shared libraries), the stub will be used. This | ||||
|      assumes that the name of the stub function is the name of the function + | ||||
|      "_stub". */ | ||||
| #define LSX_DLENTRY_STUB(f,x, ret, func, args)    f(x, ret, func, args, NULL, func##_stub, func) | ||||
| 
 | ||||
|   /* LSX_DLFUNC_IS_STUB: returns true if the named function is a do-nothing
 | ||||
|      stub. Assumes that the name of the stub function is the name of the | ||||
|      function + "_stub". */ | ||||
| #define LSX_DLFUNC_IS_STUB(ptr_container, func) ((ptr_container)->func == func##_stub) | ||||
| 
 | ||||
| #endif | ||||
| @ -1,370 +0,0 @@ | ||||
| /* src/soxconfig.h.  Generated from soxconfig.h.in by configure.  */ | ||||
| /* src/soxconfig.h.in.  Generated from configure.ac by autoheader.  */ | ||||
| 
 | ||||
| /* Define if building universal (internal helper macro) */ | ||||
| /* #undef AC_APPLE_UNIVERSAL_BUILD */ | ||||
| 
 | ||||
| /* Define to dlopen() amrnb. */ | ||||
| /* #undef DL_AMRNB */ | ||||
| 
 | ||||
| /* Define to dlopen() amrwb. */ | ||||
| /* #undef DL_AMRWB */ | ||||
| 
 | ||||
| /* Define to dlopen() lame. */ | ||||
| /* #undef DL_LAME */ | ||||
| 
 | ||||
| /* Define to dlopen() mad. */ | ||||
| /* #undef DL_MAD */ | ||||
| 
 | ||||
| /* Define to dlopen() sndfile. */ | ||||
| /* #undef DL_SNDFILE */ | ||||
| 
 | ||||
| /* Define to dlopen() libtwolame. */ | ||||
| /* #undef DL_TWOLAME */ | ||||
| 
 | ||||
| /* Define if SSP C support is enabled. */ | ||||
| #define ENABLE_SSP_CC 1 | ||||
| 
 | ||||
| /* Define if you are using an external GSM library */ | ||||
| /* #undef EXTERNAL_GSM */ | ||||
| 
 | ||||
| /* Define if you are using an external LPC10 library */ | ||||
| /* #undef EXTERNAL_LPC10 */ | ||||
| 
 | ||||
| /* Define to 1 if you have alsa. */ | ||||
| /* #undef HAVE_ALSA */ | ||||
| 
 | ||||
| /* Define to 1 if you have amrnb. */ | ||||
| /* #undef HAVE_AMRNB */ | ||||
| 
 | ||||
| /* Define to 1 if you have amrwb. */ | ||||
| /* #undef HAVE_AMRWB */ | ||||
| 
 | ||||
| /* Define to 1 if you have the <amrwb/dec.h> header file. */ | ||||
| /* #undef HAVE_AMRWB_DEC_H */ | ||||
| 
 | ||||
| /* Define to 1 if you have ao. */ | ||||
| /* #undef HAVE_AO */ | ||||
| 
 | ||||
| /* Define to 1 if you have the <byteswap.h> header file. */ | ||||
| #define HAVE_BYTESWAP_H 1 | ||||
| 
 | ||||
| /* Define to 1 if you have coreaudio. */ | ||||
| /* #undef HAVE_COREAUDIO */ | ||||
| 
 | ||||
| /* 1 if DISTRO is defined */ | ||||
| /* #undef HAVE_DISTRO */ | ||||
| 
 | ||||
| /* Define to 1 if you have the <dlfcn.h> header file. */ | ||||
| #define HAVE_DLFCN_H 1 | ||||
| 
 | ||||
| /* Define to 1 if you have the <fcntl.h> header file. */ | ||||
| #define HAVE_FCNTL_H 1 | ||||
| 
 | ||||
| /* Define to 1 if you have the <fenv.h> header file. */ | ||||
| #define HAVE_FENV_H 1 | ||||
| 
 | ||||
| /* Define to 1 if you have flac. */ | ||||
| /* #undef HAVE_FLAC */ | ||||
| 
 | ||||
| /* Define to 1 if you have the `fmemopen' function. */ | ||||
| /* #undef HAVE_FMEMOPEN */ | ||||
| 
 | ||||
| /* Define to 1 if fseeko (and presumably ftello) exists and is declared. */ | ||||
| /* #undef HAVE_FSEEKO */ | ||||
| 
 | ||||
| /* Define to 1 if you have the `gettimeofday' function. */ | ||||
| #define HAVE_GETTIMEOFDAY 1 | ||||
| 
 | ||||
| /* Define to 1 if you have the <glob.h> header file. */ | ||||
| //#define HAVE_GLOB_H 1 //TODO
 | ||||
| 
 | ||||
| /* Define to 1 if you have gsm. */ | ||||
| //#define HAVE_GSM 1 //TODO
 | ||||
| 
 | ||||
| /* Define to 1 if you have the <gsm/gsm.h> header file. */ | ||||
| /* #undef HAVE_GSM_GSM_H */ | ||||
| 
 | ||||
| /* Define to 1 if you have the <gsm.h> header file. */ | ||||
| /* #undef HAVE_GSM_H */ | ||||
| 
 | ||||
| /* Define to 1 if you have id3tag. */ | ||||
| /* #undef HAVE_ID3TAG */ | ||||
| 
 | ||||
| /* Define to 1 if you have the <inttypes.h> header file. */ | ||||
| #define HAVE_INTTYPES_H 1 | ||||
| 
 | ||||
| /* 1 if should enable LADSPA */ | ||||
| /* #undef HAVE_LADSPA_H */ | ||||
| 
 | ||||
| /* Define to 1 if you have the <lame.h> header file. */ | ||||
| /* #undef HAVE_LAME_H */ | ||||
| 
 | ||||
| /* Define to 1 if lame supports optional ID3 tags. */ | ||||
| /* #undef HAVE_LAME_ID3TAG */ | ||||
| 
 | ||||
| /* Define to 1 if you have the <lame/lame.h> header file. */ | ||||
| /* #undef HAVE_LAME_LAME_H */ | ||||
| 
 | ||||
| /* Define to 1 if you have libltdl */ | ||||
| /* #undef HAVE_LIBLTDL */ | ||||
| 
 | ||||
| /* Define to 1 if you have the <libpng/png.h> header file. */ | ||||
| /* #undef HAVE_LIBPNG_PNG_H */ | ||||
| 
 | ||||
| /* Define to 1 if you have lpc10. */ | ||||
| //#define HAVE_LPC10 1 //TODO
 | ||||
| 
 | ||||
| /* Define to 1 if you have the <lpc10.h> header file. */ | ||||
| /* #undef HAVE_LPC10_H */ | ||||
| 
 | ||||
| /* Define to 1 if you have the `lrint' function. */ | ||||
| #define HAVE_LRINT 1 | ||||
| 
 | ||||
| /* Define to 1 if you have the <ltdl.h> header file. */ | ||||
| /* #undef HAVE_LTDL_H */ | ||||
| 
 | ||||
| /* Define to 1 if you have the <machine/soundcard.h> header file. */ | ||||
| /* #undef HAVE_MACHINE_SOUNDCARD_H */ | ||||
| 
 | ||||
| /* Define to 1 if you have the <mad.h> header file. */ | ||||
| /* #undef HAVE_MAD_H */ | ||||
| 
 | ||||
| /* Define to 1 if you have magic. */ | ||||
| /* #undef HAVE_MAGIC */ | ||||
| 
 | ||||
| /* Define to 1 if you have the <memory.h> header file. */ | ||||
| #define HAVE_MEMORY_H 1 | ||||
| 
 | ||||
| /* Define to 1 if you have the `mkstemp' function. */ | ||||
| #define HAVE_MKSTEMP 1 | ||||
| 
 | ||||
| /* Define to 1 if you have mp3. */ | ||||
| /* #undef HAVE_MP3 */ | ||||
| 
 | ||||
| /* Define to 1 if you have oggvorbis. */ | ||||
| /* #undef HAVE_OGG_VORBIS */ | ||||
| 
 | ||||
| /* Define to 1 if you have the <opencore-amrnb/interf_dec.h> header file. */ | ||||
| /* #undef HAVE_OPENCORE_AMRNB_INTERF_DEC_H */ | ||||
| 
 | ||||
| /* Define to 1 if you have the <opencore-amrwb/dec_if.h> header file. */ | ||||
| /* #undef HAVE_OPENCORE_AMRWB_DEC_IF_H */ | ||||
| 
 | ||||
| /* Define to 1 if you have opus. */ | ||||
| //#define HAVE_OPUS 1 //TODO
 | ||||
| 
 | ||||
| /* Define to 1 if you have oss. */ | ||||
| /* #undef HAVE_OSS */ | ||||
| 
 | ||||
| /* Define to 1 if you have PNG. */ | ||||
| /* #undef HAVE_PNG */ | ||||
| 
 | ||||
| /* Define to 1 if you have the <png.h> header file. */ | ||||
| /* #undef HAVE_PNG_H */ | ||||
| 
 | ||||
| /* Define to 1 if you have the `popen' function. */ | ||||
| #define HAVE_POPEN 1 | ||||
| 
 | ||||
| /* Define to 1 if you have pulseaudio. */ | ||||
| /* #undef HAVE_PULSEAUDIO */ | ||||
| 
 | ||||
| /* Define if you have libsndfile with SFC_SFC_SET_SCALE_INT_FLOAT_WRITE */ | ||||
| #define HAVE_SFC_SET_SCALE_INT_FLOAT_WRITE 1 | ||||
| 
 | ||||
| /* Define to 1 if you have sndfile. */ | ||||
| /* #undef HAVE_SNDFILE */ | ||||
| 
 | ||||
| /* Define if you have libsndfile >= 1.0.18 */ | ||||
| #define HAVE_SNDFILE_1_0_18 1 | ||||
| 
 | ||||
| /* Define if you have <sndfile.h> */ | ||||
| #define HAVE_SNDFILE_H 1 | ||||
| 
 | ||||
| /* Define to 1 if you have sndio. */ | ||||
| /* #undef HAVE_SNDIO */ | ||||
| 
 | ||||
| /* Define to 1 if you have the <stdint.h> header file. */ | ||||
| #define HAVE_STDINT_H 1 | ||||
| 
 | ||||
| /* Define to 1 if you have the <stdlib.h> header file. */ | ||||
| #define HAVE_STDLIB_H 1 | ||||
| 
 | ||||
| /* Define to 1 if you have the `strcasecmp' function. */ | ||||
| #define HAVE_STRCASECMP 1 | ||||
| 
 | ||||
| /* Define to 1 if you have the `strdup' function. */ | ||||
| #define HAVE_STRDUP 1 | ||||
| 
 | ||||
| /* Define to 1 if you have the <strings.h> header file. */ | ||||
| #define HAVE_STRINGS_H 1 | ||||
| 
 | ||||
| /* Define to 1 if you have the <string.h> header file. */ | ||||
| #define HAVE_STRING_H 1 | ||||
| 
 | ||||
| /* Define to 1 if you have sunaudio. */ | ||||
| /* #undef HAVE_SUN_AUDIO */ | ||||
| 
 | ||||
| /* Define to 1 if you have the <sun/audioio.h> header file. */ | ||||
| /* #undef HAVE_SUN_AUDIOIO_H */ | ||||
| 
 | ||||
| /* Define to 1 if you have the <sys/audioio.h> header file. */ | ||||
| /* #undef HAVE_SYS_AUDIOIO_H */ | ||||
| 
 | ||||
| /* Define to 1 if you have the <sys/soundcard.h> header file. */ | ||||
| /* #undef HAVE_SYS_SOUNDCARD_H */ | ||||
| 
 | ||||
| /* Define to 1 if you have the <sys/stat.h> header file. */ | ||||
| #define HAVE_SYS_STAT_H 1 | ||||
| 
 | ||||
| /* Define to 1 if you have the <sys/timeb.h> header file. */ | ||||
| /* #undef HAVE_SYS_TIMEB_H */ | ||||
| 
 | ||||
| /* Define to 1 if you have the <sys/time.h> header file. */ | ||||
| #define HAVE_SYS_TIME_H 1 | ||||
| 
 | ||||
| /* Define to 1 if you have the <sys/types.h> header file. */ | ||||
| #define HAVE_SYS_TYPES_H 1 | ||||
| 
 | ||||
| /* Define to 1 if you have the <sys/utsname.h> header file. */ | ||||
| #define HAVE_SYS_UTSNAME_H 1 | ||||
| 
 | ||||
| /* Define to 1 if you have the <termios.h> header file. */ | ||||
| #define HAVE_TERMIOS_H 1 | ||||
| 
 | ||||
| /* Define to 1 if you have the <twolame.h> header file. */ | ||||
| /* #undef HAVE_TWOLAME_H */ | ||||
| 
 | ||||
| /* Define to 1 if you have the <unistd.h> header file. */ | ||||
| #define HAVE_UNISTD_H 1 | ||||
| 
 | ||||
| /* Define to 1 if you have the `vsnprintf' function. */ | ||||
| #define HAVE_VSNPRINTF 1 | ||||
| 
 | ||||
| /* Define to 1 if you have waveaudio. */ | ||||
| /* #undef HAVE_WAVEAUDIO */ | ||||
| 
 | ||||
| /* Define to 1 if you have wavpack. */ | ||||
| /* #undef HAVE_WAVPACK */ | ||||
| 
 | ||||
| /* Define to 1 to use win32 glob */ | ||||
| /* #undef HAVE_WIN32_GLOB_H */ | ||||
| 
 | ||||
| /* Define to 1 to use internal win32 ltdl */ | ||||
| /* #undef HAVE_WIN32_LTDL_H */ | ||||
| 
 | ||||
| /* Define to the sub-directory where libtool stores uninstalled libraries. */ | ||||
| #define LT_OBJDIR ".libs/" | ||||
| 
 | ||||
| /* Name of package */ | ||||
| #define PACKAGE "sox" | ||||
| 
 | ||||
| /* Define to the address where bug reports for this package should be sent. */ | ||||
| #define PACKAGE_BUGREPORT "sox-devel@lists.sourceforge.net" | ||||
| 
 | ||||
| /* Define to the full name of this package. */ | ||||
| #define PACKAGE_NAME "SoX" | ||||
| 
 | ||||
| /* Define to the full name and version of this package. */ | ||||
| #define PACKAGE_STRING "SoX 14.4.2" | ||||
| 
 | ||||
| /* Define to the one symbol short name of this package. */ | ||||
| #define PACKAGE_TARNAME "sox" | ||||
| 
 | ||||
| /* Define to the home page for this package. */ | ||||
| #define PACKAGE_URL "" | ||||
| 
 | ||||
| /* Define to the version of this package. */ | ||||
| #define PACKAGE_VERSION "14.4.2" | ||||
| 
 | ||||
| /* Define to 1 if you have static alsa. */ | ||||
| /* #undef STATIC_ALSA */ | ||||
| 
 | ||||
| /* Define to 1 if you have static amrnb. */ | ||||
| /* #undef STATIC_AMRNB */ | ||||
| 
 | ||||
| /* Define to 1 if you have static amrwb. */ | ||||
| /* #undef STATIC_AMRWB */ | ||||
| 
 | ||||
| /* Define to 1 if you have static ao. */ | ||||
| /* #undef STATIC_AO */ | ||||
| 
 | ||||
| /* Define to 1 if you have static coreaudio. */ | ||||
| /* #undef STATIC_COREAUDIO */ | ||||
| 
 | ||||
| /* Define to 1 if you have static flac. */ | ||||
| /* #undef STATIC_FLAC */ | ||||
| 
 | ||||
| /* Define to 1 if you have static gsm. */ | ||||
| #define STATIC_GSM 1 | ||||
| 
 | ||||
| /* Define to 1 if you have static lpc10. */ | ||||
| #define STATIC_LPC10 1 | ||||
| 
 | ||||
| /* Define to 1 if you have static mp3. */ | ||||
| /* #undef STATIC_MP3 */ | ||||
| 
 | ||||
| /* Define to 1 if you have static oggvorbis. */ | ||||
| /* #undef STATIC_OGG_VORBIS */ | ||||
| 
 | ||||
| /* Define to 1 if you have static opus. */ | ||||
| #define STATIC_OPUS 1 | ||||
| 
 | ||||
| /* Define to 1 if you have static oss. */ | ||||
| /* #undef STATIC_OSS */ | ||||
| 
 | ||||
| /* Define to 1 if you have static pulseaudio. */ | ||||
| /* #undef STATIC_PULSEAUDIO */ | ||||
| 
 | ||||
| /* Define to 1 if you have static sndfile. */ | ||||
| /* #undef STATIC_SNDFILE */ | ||||
| 
 | ||||
| /* Define to 1 if you have static sndio. */ | ||||
| /* #undef STATIC_SNDIO */ | ||||
| 
 | ||||
| /* Define to 1 if you have static sunaudio. */ | ||||
| /* #undef STATIC_SUN_AUDIO */ | ||||
| 
 | ||||
| /* Define to 1 if you have static waveaudio. */ | ||||
| /* #undef STATIC_WAVEAUDIO */ | ||||
| 
 | ||||
| /* Define to 1 if you have static wavpack. */ | ||||
| /* #undef STATIC_WAVPACK */ | ||||
| 
 | ||||
| /* Define to 1 if you have the ANSI C header files. */ | ||||
| #define STDC_HEADERS 1 | ||||
| 
 | ||||
| /* Version number of package */ | ||||
| #define VERSION "14.4.2" | ||||
| 
 | ||||
| /* Define WORDS_BIGENDIAN to 1 if your processor stores words with the most
 | ||||
|    significant byte first (like Motorola and SPARC, unlike Intel). */ | ||||
| #if defined AC_APPLE_UNIVERSAL_BUILD | ||||
| # if defined __BIG_ENDIAN__ | ||||
| #  define WORDS_BIGENDIAN 1 | ||||
| # endif | ||||
| #else | ||||
| # ifndef WORDS_BIGENDIAN | ||||
| /* #  undef WORDS_BIGENDIAN */ | ||||
| # endif | ||||
| #endif | ||||
| 
 | ||||
| /* Enable large inode numbers on Mac OS X 10.5.  */ | ||||
| #ifndef _DARWIN_USE_64_BIT_INODE | ||||
| # define _DARWIN_USE_64_BIT_INODE 1 | ||||
| #endif | ||||
| 
 | ||||
| /* Number of bits in a file offset, on hosts where this is settable. */ | ||||
| #define _FILE_OFFSET_BITS 64 | ||||
| 
 | ||||
| /* Define to 1 to make fseeko visible on some hosts (e.g. glibc 2.2). */ | ||||
| #define _LARGEFILE_SOURCE 1 | ||||
| 
 | ||||
| /* Define for large files, on AIX-style hosts. */ | ||||
| /* #undef _LARGE_FILES */ | ||||
| 
 | ||||
| /* Define to `__inline__' or `__inline' if that's what the C compiler
 | ||||
|    calls it, or to nothing if 'inline' is not supported under any name.  */ | ||||
| #ifndef __cplusplus | ||||
| /* #undef inline */ | ||||
| #endif | ||||
| @ -1,47 +0,0 @@ | ||||
| #include "soxconfig.h" | ||||
| 
 | ||||
| #ifdef _OPENMP | ||||
|   #if _OPENMP >= 200805 /* OpenMP 3.0 */ | ||||
|     #define HAVE_OPENMP 1 | ||||
|   #endif | ||||
|   #if _OPENMP >= 201107 /* OpenMP 3.1 */ | ||||
|     #define HAVE_OPENMP_3_1 1 | ||||
|   #endif | ||||
| #endif | ||||
| 
 | ||||
| #ifdef HAVE_OPENMP | ||||
|   #include <omp.h> | ||||
| #else | ||||
| 
 | ||||
| typedef int omp_lock_t; | ||||
| typedef int omp_nest_lock_t; | ||||
| 
 | ||||
| #define omp_set_num_threads(int) (void)0 | ||||
| #define omp_get_num_threads() 1 | ||||
| #define omp_get_max_threads() 1 | ||||
| #define omp_get_thread_num() 0 | ||||
| #define omp_get_num_procs() 1 | ||||
| #define omp_in_parallel() 1 | ||||
| 
 | ||||
| #define omp_set_dynamic(int) (void)0 | ||||
| #define omp_get_dynamic() 0 | ||||
| 
 | ||||
| #define omp_set_nested(int) (void)0 | ||||
| #define omp_get_nested() 0 | ||||
| 
 | ||||
| #define omp_init_lock(omp_lock_t) (void)0 | ||||
| #define omp_destroy_lock(omp_lock_t) (void)0 | ||||
| #define omp_set_lock(omp_lock_t) (void)0 | ||||
| #define omp_unset_lock(omp_lock_t) (void)0 | ||||
| #define omp_test_lock(omp_lock_t) 0 | ||||
| 
 | ||||
| #define omp_init_nest_lock(omp_nest_lock_t) (void)0 | ||||
| #define omp_destroy_nest_lock(omp_nest_lock_t) (void)0 | ||||
| #define omp_set_nest_lock(omp_nest_lock_t) (void)0 | ||||
| #define omp_unset_nest_lock(omp_nest_lock_t) (void)0 | ||||
| #define omp_test_nest_lock(omp_nest_lock_t) 0 | ||||
| 
 | ||||
| #define omp_get_wtime() 0 | ||||
| #define omp_get_wtick() 0 | ||||
| 
 | ||||
| #endif | ||||
| @ -1,73 +0,0 @@ | ||||
| /* libSoX Effect: Adjust the audio speed (pitch and tempo together)
 | ||||
|  * (c) 2006,8 robs@users.sourceforge.net | ||||
|  * | ||||
|  * This library is free software; you can redistribute it and/or modify it | ||||
|  * under the terms of the GNU Lesser General Public License as published by | ||||
|  * the Free Software Foundation; either version 2.1 of the License, or (at | ||||
|  * your option) any later version. | ||||
|  * | ||||
|  * This library is distributed in the hope that it will be useful, but | ||||
|  * WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser | ||||
|  * General Public License for more details. | ||||
|  * | ||||
|  * You should have received a copy of the GNU Lesser General Public License | ||||
|  * along with this library; if not, write to the Free Software Foundation, | ||||
|  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA | ||||
|  * | ||||
|  * | ||||
|  * Adjustment is given as the ratio of the new speed to the old speed, or as | ||||
|  * a number of cents (100ths of a semitone) to change.  Speed change is | ||||
|  * actually performed by whichever resampling effect is in effect. | ||||
|  */ | ||||
| 
 | ||||
| #include "sox_i.h" | ||||
| #include <string.h> | ||||
| 
 | ||||
| typedef struct { | ||||
|   double factor; | ||||
| } priv_t; | ||||
| 
 | ||||
| static int getopts(sox_effect_t * effp, int argc, char * * argv) | ||||
| { | ||||
|   priv_t * p = (priv_t *) effp->priv; | ||||
|   sox_bool is_cents = sox_false; | ||||
| 
 | ||||
|   --argc, ++argv; | ||||
|   if (argc == 1) { | ||||
|     char c, dummy; | ||||
|     int scanned = sscanf(*argv, "%lf%c %c", &p->factor, &c, &dummy); | ||||
|     if (scanned == 1 || (scanned == 2 && c == 'c')) { | ||||
|       is_cents |= scanned == 2; | ||||
|       if (is_cents || p->factor > 0) { | ||||
|         p->factor = is_cents? pow(2., p->factor / 1200) : p->factor; | ||||
|         return SOX_SUCCESS; | ||||
|       } | ||||
|     } | ||||
|   } | ||||
|   return lsx_usage(effp); | ||||
| } | ||||
| 
 | ||||
| static int start(sox_effect_t * effp) | ||||
| { | ||||
|   priv_t * p = (priv_t *) effp->priv; | ||||
| 
 | ||||
|   if (p->factor == 1) | ||||
|     return SOX_EFF_NULL; | ||||
| 
 | ||||
|   effp->out_signal.rate = effp->in_signal.rate * p->factor; | ||||
| 
 | ||||
|   effp->out_signal.length = effp->in_signal.length; | ||||
|     /* audio length if measured in samples doesn't change */ | ||||
| 
 | ||||
|   return SOX_SUCCESS; | ||||
| } | ||||
| 
 | ||||
| sox_effect_handler_t const * lsx_speed_effect_fn(void) | ||||
| { | ||||
|   static sox_effect_handler_t handler = { | ||||
|     "speed", "factor[c]", | ||||
|     SOX_EFF_MCHAN | SOX_EFF_RATE | SOX_EFF_LENGTH | SOX_EFF_MODIFY, | ||||
|     getopts, start, lsx_flow_copy, 0, 0, 0, sizeof(priv_t)}; | ||||
|   return &handler; | ||||
| } | ||||
| @ -1,360 +0,0 @@ | ||||
| /* libSoX effect: change tempo (and duration) or pitch (maintain duration)
 | ||||
|  * Copyright (c) 2007,8 robs@users.sourceforge.net | ||||
|  * Based on ideas from Olli Parviainen's SoundTouch Library. | ||||
|  * | ||||
|  * This library is free software; you can redistribute it and/or modify it | ||||
|  * under the terms of the GNU Lesser General Public License as published by | ||||
|  * the Free Software Foundation; either version 2.1 of the License, or (at | ||||
|  * your option) any later version. | ||||
|  * | ||||
|  * This library is distributed in the hope that it will be useful, but | ||||
|  * WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser | ||||
|  * General Public License for more details. | ||||
|  * | ||||
|  * You should have received a copy of the GNU Lesser General Public License | ||||
|  * along with this library; if not, write to the Free Software Foundation, | ||||
|  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA | ||||
|  */ | ||||
| 
 | ||||
| #include "sox_i.h" | ||||
| #include "fifo.h" | ||||
| #include <math.h> | ||||
| 
 | ||||
| typedef struct { | ||||
|   /* Configuration parameters: */ | ||||
|   size_t channels; | ||||
|   sox_bool quick_search; /* Whether to quick search or linear search */ | ||||
|   double factor;         /* 1 for no change, < 1 for slower, > 1 for faster. */ | ||||
|   size_t search;         /* Wide samples to search for best overlap position */ | ||||
|   size_t segment;        /* Processing segment length in wide samples */ | ||||
|   size_t overlap;        /* In wide samples */ | ||||
| 
 | ||||
|   size_t process_size;   /* # input wide samples needed to process 1 segment */ | ||||
| 
 | ||||
|   /* Buffers: */ | ||||
|   fifo_t input_fifo; | ||||
|   float * overlap_buf; | ||||
|   fifo_t output_fifo; | ||||
| 
 | ||||
|   /* Counters: */ | ||||
|   uint64_t samples_in; | ||||
|   uint64_t samples_out; | ||||
|   uint64_t segments_total; | ||||
|   uint64_t skip_total; | ||||
| } tempo_t; | ||||
| 
 | ||||
| /* Waveform Similarity by least squares; works across multi-channels */ | ||||
| static float difference(const float * a, const float * b, size_t length) | ||||
| { | ||||
|   float diff = 0; | ||||
|   size_t i = 0; | ||||
| 
 | ||||
|   #define _ diff += sqr(a[i] - b[i]), ++i; /* Loop optimisation */ | ||||
|   do {_ _ _ _ _ _ _ _} while (i < length); /* N.B. length ≡ 0 (mod 8) */ | ||||
|   #undef _ | ||||
|   return diff; | ||||
| } | ||||
| 
 | ||||
| /* Find where the two segments are most alike over the overlap period. */ | ||||
| static size_t tempo_best_overlap_position(tempo_t * t, float const * new_win) | ||||
| { | ||||
|   float * f = t->overlap_buf; | ||||
|   size_t j, best_pos, prev_best_pos = (t->search + 1) >> 1, step = 64; | ||||
|   size_t i = best_pos = t->quick_search? prev_best_pos : 0; | ||||
|   float diff, least_diff = difference(new_win + t->channels * i, f, t->channels * t->overlap); | ||||
|   int k = 0; | ||||
| 
 | ||||
|   if (t->quick_search) do { /* hierarchical search */ | ||||
|     for (k = -1; k <= 1; k += 2) for (j = 1; j < 4 || step == 64; ++j) { | ||||
|       i = prev_best_pos + k * j * step; | ||||
|       if ((int)i < 0 || i >= t->search) | ||||
|         break; | ||||
|       diff = difference(new_win + t->channels * i, f, t->channels * t->overlap); | ||||
|       if (diff < least_diff) | ||||
|         least_diff = diff, best_pos = i; | ||||
|     } | ||||
|     prev_best_pos = best_pos; | ||||
|   } while (step >>= 2); | ||||
|   else for (i = 1; i < t->search; i++) { /* linear search */ | ||||
|     diff = difference(new_win + t->channels * i, f, t->channels * t->overlap); | ||||
|     if (diff < least_diff) | ||||
|       least_diff = diff, best_pos = i; | ||||
|   } | ||||
|   return best_pos; | ||||
| } | ||||
| 
 | ||||
| static void tempo_overlap( | ||||
|     tempo_t * t, const float * in1, const float * in2, float * output) | ||||
| { | ||||
|   size_t i, j, k = 0; | ||||
|   float fade_step = 1.0f / (float) t->overlap; | ||||
| 
 | ||||
|   for (i = 0; i < t->overlap; ++i) { | ||||
|     float fade_in  = fade_step * (float) i; | ||||
|     float fade_out = 1.0f - fade_in; | ||||
|     for (j = 0; j < t->channels; ++j, ++k) | ||||
|       output[k] = in1[k] * fade_out + in2[k] * fade_in; | ||||
|   } | ||||
| } | ||||
| 
 | ||||
| static void tempo_process(tempo_t * t) | ||||
| { | ||||
|   while (fifo_occupancy(&t->input_fifo) >= t->process_size) { | ||||
|     size_t skip, offset; | ||||
| 
 | ||||
|     /* Copy or overlap the first bit to the output */ | ||||
|     if (!t->segments_total) { | ||||
|       offset = t->search / 2; | ||||
|       fifo_write(&t->output_fifo, t->overlap, (float *) fifo_read_ptr(&t->input_fifo) + t->channels * offset); | ||||
|     } else { | ||||
|       offset = tempo_best_overlap_position(t, fifo_read_ptr(&t->input_fifo)); | ||||
|       tempo_overlap(t, t->overlap_buf, | ||||
|           (float *) fifo_read_ptr(&t->input_fifo) + t->channels * offset, | ||||
|           fifo_write(&t->output_fifo, t->overlap, NULL)); | ||||
|     } | ||||
|     /* Copy the middle bit to the output */ | ||||
|     fifo_write(&t->output_fifo, t->segment - 2 * t->overlap, | ||||
|                (float *) fifo_read_ptr(&t->input_fifo) + | ||||
|                t->channels * (offset + t->overlap)); | ||||
| 
 | ||||
|     /* Copy the end bit to overlap_buf ready to be mixed with
 | ||||
|      * the beginning of the next segment. */ | ||||
|     memcpy(t->overlap_buf, | ||||
|            (float *) fifo_read_ptr(&t->input_fifo) + | ||||
|            t->channels * (offset + t->segment - t->overlap), | ||||
|            t->channels * t->overlap * sizeof(*(t->overlap_buf))); | ||||
| 
 | ||||
|     /* Advance through the input stream */ | ||||
|     skip = t->factor * (++t->segments_total * (t->segment - t->overlap)) + 0.5; | ||||
|     t->skip_total += skip -= t->skip_total; | ||||
|     fifo_read(&t->input_fifo, skip, NULL); | ||||
|   } | ||||
| } | ||||
| 
 | ||||
| static float * tempo_input(tempo_t * t, float const * samples, size_t n) | ||||
| { | ||||
|   t->samples_in += n; | ||||
|   return fifo_write(&t->input_fifo, n, samples); | ||||
| } | ||||
| 
 | ||||
| static float const * tempo_output(tempo_t * t, float * samples, size_t * n) | ||||
| { | ||||
|   t->samples_out += *n = min(*n, fifo_occupancy(&t->output_fifo)); | ||||
|   return fifo_read(&t->output_fifo, *n, samples); | ||||
| } | ||||
| 
 | ||||
| /* Flush samples remaining in overlap_buf & input_fifo to the output. */ | ||||
| static void tempo_flush(tempo_t * t) | ||||
| { | ||||
|   uint64_t samples_out = t->samples_in / t->factor + .5; | ||||
|   size_t remaining = samples_out > t->samples_out ? | ||||
|       (size_t)(samples_out - t->samples_out) : 0; | ||||
|   float * buff = lsx_calloc(128 * t->channels, sizeof(*buff)); | ||||
| 
 | ||||
|   if (remaining > 0) { | ||||
|     while (fifo_occupancy(&t->output_fifo) < remaining) { | ||||
|       tempo_input(t, buff, (size_t) 128); | ||||
|       tempo_process(t); | ||||
|     } | ||||
|     fifo_trim_to(&t->output_fifo, remaining); | ||||
|     t->samples_in = 0; | ||||
|   } | ||||
|   free(buff); | ||||
| } | ||||
| 
 | ||||
| static void tempo_setup(tempo_t * t, | ||||
|   double sample_rate, sox_bool quick_search, double factor, | ||||
|   double segment_ms, double search_ms, double overlap_ms) | ||||
| { | ||||
|   size_t max_skip; | ||||
|   t->quick_search = quick_search; | ||||
|   t->factor = factor; | ||||
|   t->segment = sample_rate * segment_ms / 1000 + .5; | ||||
|   t->search  = sample_rate * search_ms / 1000 + .5; | ||||
|   t->overlap = max(sample_rate * overlap_ms / 1000 + 4.5, 16); | ||||
|   t->overlap &= ~7; /* Make divisible by 8 for loop optimisation */ | ||||
|   if (t->overlap * 2 > t->segment) | ||||
|     t->overlap -= 8; | ||||
|   t->overlap_buf = lsx_malloc(t->overlap * t->channels * sizeof(*t->overlap_buf)); | ||||
|   max_skip = ceil(factor * (t->segment - t->overlap)); | ||||
|   t->process_size = max(max_skip + t->overlap, t->segment) + t->search; | ||||
|   memset(fifo_reserve(&t->input_fifo, t->search / 2), 0, (t->search / 2) * t->channels * sizeof(float)); | ||||
| } | ||||
| 
 | ||||
| static void tempo_delete(tempo_t * t) | ||||
| { | ||||
|   free(t->overlap_buf); | ||||
|   fifo_delete(&t->output_fifo); | ||||
|   fifo_delete(&t->input_fifo); | ||||
|   free(t); | ||||
| } | ||||
| 
 | ||||
| static tempo_t * tempo_create(size_t channels) | ||||
| { | ||||
|   tempo_t * t = lsx_calloc(1, sizeof(*t)); | ||||
|   t->channels = channels; | ||||
|   fifo_create(&t->input_fifo, t->channels * sizeof(float)); | ||||
|   fifo_create(&t->output_fifo, t->channels * sizeof(float)); | ||||
|   return t; | ||||
| } | ||||
| 
 | ||||
| /*------------------------------- SoX Wrapper --------------------------------*/ | ||||
| 
 | ||||
| typedef struct { | ||||
|   tempo_t     * tempo; | ||||
|   sox_bool    quick_search; | ||||
|   double      factor, segment_ms, search_ms, overlap_ms; | ||||
| } priv_t; | ||||
| 
 | ||||
| static int getopts(sox_effect_t * effp, int argc, char **argv) | ||||
| { | ||||
|   priv_t * p = (priv_t *)effp->priv; | ||||
|   enum {Default, Music, Speech, Linear} profile = Default; | ||||
|   static const double segments_ms [] = {   82,82,  35  , 20}; | ||||
|   static const double segments_pow[] = {    0, 1, .33  , 1}; | ||||
|   static const double overlaps_div[] = {6.833, 7,  2.5 , 2}; | ||||
|   static const double searches_div[] = {5.587, 6,  2.14, 2}; | ||||
|   int c; | ||||
|   lsx_getopt_t optstate; | ||||
|   lsx_getopt_init(argc, argv, "+qmls", NULL, lsx_getopt_flag_none, 1, &optstate); | ||||
| 
 | ||||
|   p->segment_ms = p->search_ms = p->overlap_ms = HUGE_VAL; | ||||
|   while ((c = lsx_getopt(&optstate)) != -1) switch (c) { | ||||
|     case 'q': p->quick_search  = sox_true;   break; | ||||
|     case 'm': profile = Music; break; | ||||
|     case 's': profile = Speech; break; | ||||
|     case 'l': profile = Linear; p->search_ms = 0; break; | ||||
|     default: lsx_fail("unknown option `-%c'", optstate.opt); return lsx_usage(effp); | ||||
|   } | ||||
|   argc -= optstate.ind, argv += optstate.ind; | ||||
|   do {                    /* break-able block */ | ||||
|     NUMERIC_PARAMETER(factor      ,0.1 , 100 ) | ||||
|     NUMERIC_PARAMETER(segment_ms  , 10 , 120) | ||||
|     NUMERIC_PARAMETER(search_ms   , 0  , 30 ) | ||||
|     NUMERIC_PARAMETER(overlap_ms  , 0  , 30 ) | ||||
|   } while (0); | ||||
| 
 | ||||
|   if (p->segment_ms == HUGE_VAL) | ||||
|     p->segment_ms = max(10, segments_ms[profile] / max(pow(p->factor, segments_pow[profile]), 1)); | ||||
|   if (p->overlap_ms == HUGE_VAL) | ||||
|     p->overlap_ms = p->segment_ms / overlaps_div[profile]; | ||||
|   if (p->search_ms == HUGE_VAL) | ||||
|     p->search_ms = p->segment_ms / searches_div[profile]; | ||||
| 
 | ||||
|   p->overlap_ms = min(p->overlap_ms, p->segment_ms / 2); | ||||
|   lsx_report("quick_search=%u factor=%g segment=%g search=%g overlap=%g", | ||||
|     p->quick_search, p->factor, p->segment_ms, p->search_ms, p->overlap_ms); | ||||
|   return argc? lsx_usage(effp) : SOX_SUCCESS; | ||||
| } | ||||
| 
 | ||||
| static int start(sox_effect_t * effp) | ||||
| { | ||||
|   priv_t * p = (priv_t *)effp->priv; | ||||
| 
 | ||||
|   if (p->factor == 1) | ||||
|     return SOX_EFF_NULL; | ||||
| 
 | ||||
|   p->tempo = tempo_create((size_t)effp->in_signal.channels); | ||||
|   tempo_setup(p->tempo, effp->in_signal.rate, p->quick_search, p->factor, | ||||
|       p->segment_ms, p->search_ms, p->overlap_ms); | ||||
| 
 | ||||
|   effp->out_signal.length = SOX_UNKNOWN_LEN; | ||||
|   if (effp->in_signal.length != SOX_UNKNOWN_LEN) { | ||||
|     uint64_t in_length = effp->in_signal.length / effp->in_signal.channels; | ||||
|     uint64_t out_length = in_length / p->factor + .5; | ||||
|     effp->out_signal.length = out_length * effp->in_signal.channels; | ||||
|   } | ||||
| 
 | ||||
|   return SOX_SUCCESS; | ||||
| } | ||||
| 
 | ||||
| static int flow(sox_effect_t * effp, const sox_sample_t * ibuf, | ||||
|                 sox_sample_t * obuf, size_t * isamp, size_t * osamp) | ||||
| { | ||||
|   priv_t * p = (priv_t *)effp->priv; | ||||
|   size_t i, odone = *osamp /= effp->in_signal.channels; | ||||
|   float const * s = tempo_output(p->tempo, NULL, &odone); | ||||
|   SOX_SAMPLE_LOCALS; | ||||
| 
 | ||||
|   for (i = 0; i < odone * effp->in_signal.channels; ++i) | ||||
|     *obuf++ = SOX_FLOAT_32BIT_TO_SAMPLE(*s++, effp->clips); | ||||
| 
 | ||||
|   if (*isamp && odone < *osamp) { | ||||
|     float * t = tempo_input(p->tempo, NULL, *isamp / effp->in_signal.channels); | ||||
|     for (i = *isamp; i; --i) | ||||
|       *t++ = SOX_SAMPLE_TO_FLOAT_32BIT(*ibuf++, effp->clips); | ||||
|     tempo_process(p->tempo); | ||||
|   } | ||||
|   else *isamp = 0; | ||||
| 
 | ||||
|   *osamp = odone * effp->in_signal.channels; | ||||
|   return SOX_SUCCESS; | ||||
| } | ||||
| 
 | ||||
| static int drain(sox_effect_t * effp, sox_sample_t * obuf, size_t * osamp) | ||||
| { | ||||
|   priv_t * p = (priv_t *)effp->priv; | ||||
|   static size_t isamp = 0; | ||||
|   tempo_flush(p->tempo); | ||||
|   return flow(effp, 0, obuf, &isamp, osamp); | ||||
| } | ||||
| 
 | ||||
| static int stop(sox_effect_t * effp) | ||||
| { | ||||
|   priv_t * p = (priv_t *)effp->priv; | ||||
|   tempo_delete(p->tempo); | ||||
|   return SOX_SUCCESS; | ||||
| } | ||||
| 
 | ||||
| sox_effect_handler_t const * lsx_tempo_effect_fn(void) | ||||
| { | ||||
|   static sox_effect_handler_t handler = { | ||||
|     "tempo", "[-q] [-m | -s | -l] factor [segment-ms [search-ms [overlap-ms]]]", | ||||
|     SOX_EFF_MCHAN | SOX_EFF_LENGTH, | ||||
|     getopts, start, flow, drain, stop, NULL, sizeof(priv_t) | ||||
|   }; | ||||
|   return &handler; | ||||
| } | ||||
| 
 | ||||
| /*---------------------------------- pitch -----------------------------------*/ | ||||
| 
 | ||||
| static int pitch_getopts(sox_effect_t * effp, int argc, char **argv) | ||||
| { | ||||
|   double d; | ||||
|   char dummy, arg[100], **argv2 = lsx_malloc(argc * sizeof(*argv2)); | ||||
|   int result, pos = (argc > 1 && !strcmp(argv[1], "-q"))? 2 : 1; | ||||
| 
 | ||||
|   if (argc <= pos || sscanf(argv[pos], "%lf %c", &d, &dummy) != 1) | ||||
|     return lsx_usage(effp); | ||||
| 
 | ||||
|   d = pow(2., d / 1200);  /* cents --> factor */ | ||||
|   sprintf(arg, "%g", 1 / d); | ||||
|   memcpy(argv2, argv, argc * sizeof(*argv2)); | ||||
|   argv2[pos] = arg; | ||||
|   result = getopts(effp, argc, argv2); | ||||
|   free(argv2); | ||||
|   return result; | ||||
| } | ||||
| 
 | ||||
| static int pitch_start(sox_effect_t * effp) | ||||
| { | ||||
|   priv_t * p = (priv_t *) effp->priv; | ||||
|   int result = start(effp); | ||||
| 
 | ||||
|   effp->out_signal.rate = effp->in_signal.rate / p->factor; | ||||
|   return result; | ||||
| } | ||||
| 
 | ||||
| sox_effect_handler_t const * lsx_pitch_effect_fn(void) | ||||
| { | ||||
|   static sox_effect_handler_t handler; | ||||
|   handler = *lsx_tempo_effect_fn(); | ||||
|   handler.name = "pitch"; | ||||
|   handler.usage = "[-q] shift-in-cents [segment-ms [search-ms [overlap-ms]]]", | ||||
|   handler.getopts = pitch_getopts; | ||||
|   handler.start = pitch_start; | ||||
|   handler.flags &= ~SOX_EFF_LENGTH; | ||||
|   handler.flags |= SOX_EFF_RATE; | ||||
|   return &handler; | ||||
| } | ||||
| @ -1,64 +0,0 @@ | ||||
| /* libSoX effect: Upsample (zero stuff)    (c) 2011 robs@users.sourceforge.net
 | ||||
|  * | ||||
|  * Sometimes filters perform better at higher sampling rates, so e.g. | ||||
|  *   sox -r 48k input output upsample 4 filter rate 48k vol 4 | ||||
|  * | ||||
|  * This library is free software; you can redistribute it and/or modify it | ||||
|  * under the terms of the GNU Lesser General Public License as published by | ||||
|  * the Free Software Foundation; either version 2.1 of the License, or (at | ||||
|  * your option) any later version. | ||||
|  * | ||||
|  * This library is distributed in the hope that it will be useful, but | ||||
|  * WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser | ||||
|  * General Public License for more details. | ||||
|  * | ||||
|  * You should have received a copy of the GNU Lesser General Public License | ||||
|  * along with this library; if not, write to the Free Software Foundation, | ||||
|  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA | ||||
|  */ | ||||
| 
 | ||||
| #include "sox_i.h" | ||||
| 
 | ||||
| typedef struct {unsigned factor, pos;} priv_t; | ||||
| 
 | ||||
| static int create(sox_effect_t * effp, int argc, char * * argv) | ||||
| { | ||||
|   priv_t * p = (priv_t *)effp->priv; | ||||
|   p->factor = 2; | ||||
|   --argc, ++argv; | ||||
|   do {NUMERIC_PARAMETER(factor, 1, 256)} while (0); | ||||
|   return argc? lsx_usage(effp) : SOX_SUCCESS; | ||||
| } | ||||
| 
 | ||||
| static int start(sox_effect_t * effp) | ||||
| { | ||||
|   priv_t * p = (priv_t *) effp->priv; | ||||
|   effp->out_signal.rate = effp->in_signal.rate * p->factor; | ||||
|   return p->factor == 1? SOX_EFF_NULL : SOX_SUCCESS; | ||||
| } | ||||
| 
 | ||||
| static int flow(sox_effect_t * effp, const sox_sample_t * ibuf, | ||||
|     sox_sample_t * obuf, size_t * isamp, size_t * osamp) | ||||
| { | ||||
|   priv_t * p = (priv_t *)effp->priv; | ||||
|   size_t ilen = *isamp, olen = *osamp; | ||||
|   while (sox_true) { | ||||
|     for (; p->pos && olen; p->pos = (p->pos + 1) % p->factor, --olen) | ||||
|       *obuf++ = 0; | ||||
|     if (!ilen || !olen) | ||||
|       break; | ||||
|     *obuf++ = *ibuf++; | ||||
|     --olen, --ilen; | ||||
|     ++p->pos; | ||||
|   } | ||||
|   *isamp -= ilen, *osamp -= olen; | ||||
|   return SOX_SUCCESS; | ||||
| } | ||||
| 
 | ||||
| sox_effect_handler_t const * lsx_upsample_effect_fn(void) | ||||
| { | ||||
|   static sox_effect_handler_t handler = {"upsample", "[factor (2)]", | ||||
|     SOX_EFF_RATE | SOX_EFF_MODIFY, create, start, flow, NULL, NULL, NULL, sizeof(priv_t)}; | ||||
|   return &handler; | ||||
| } | ||||
| @ -1,304 +0,0 @@ | ||||
| /* General purpose, i.e. non SoX specific, utility functions.
 | ||||
|  * Copyright (c) 2007-8 robs@users.sourceforge.net | ||||
|  * | ||||
|  * This library is free software; you can redistribute it and/or modify it | ||||
|  * under the terms of the GNU Lesser General Public License as published by | ||||
|  * the Free Software Foundation; either version 2.1 of the License, or (at | ||||
|  * your option) any later version. | ||||
|  * | ||||
|  * This library is distributed in the hope that it will be useful, but | ||||
|  * WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser | ||||
|  * General Public License for more details. | ||||
|  * | ||||
|  * You should have received a copy of the GNU Lesser General Public License | ||||
|  * along with this library; if not, write to the Free Software Foundation, | ||||
|  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA | ||||
|  */ | ||||
| 
 | ||||
| #include "sox_i.h" | ||||
| #include <ctype.h> | ||||
| #include <stdio.h> | ||||
| 
 | ||||
| int lsx_strcasecmp(const char * s1, const char * s2) | ||||
| { | ||||
| #if defined(HAVE_STRCASECMP) | ||||
|   return strcasecmp(s1, s2); | ||||
| #elif defined(_MSC_VER) | ||||
|   return _stricmp(s1, s2); | ||||
| #else | ||||
|   while (*s1 && (toupper(*s1) == toupper(*s2))) | ||||
|     s1++, s2++; | ||||
|   return toupper(*s1) - toupper(*s2); | ||||
| #endif | ||||
| } | ||||
| 
 | ||||
| int lsx_strncasecmp(char const * s1, char const * s2, size_t n) | ||||
| { | ||||
| #if defined(HAVE_STRCASECMP) | ||||
|   return strncasecmp(s1, s2, n); | ||||
| #elif defined(_MSC_VER) | ||||
|   return _strnicmp(s1, s2, n); | ||||
| #else | ||||
|   while (--n && *s1 && (toupper(*s1) == toupper(*s2))) | ||||
|     s1++, s2++; | ||||
|   return toupper(*s1) - toupper(*s2); | ||||
| #endif | ||||
| } | ||||
| 
 | ||||
| sox_bool lsx_strends(char const * str, char const * end) | ||||
| { | ||||
|   size_t str_len = strlen(str), end_len = strlen(end); | ||||
|   return str_len >= end_len && !strcmp(str + str_len - end_len, end); | ||||
| } | ||||
| 
 | ||||
| char const * lsx_find_file_extension(char const * pathname) | ||||
| { | ||||
|   /* First, chop off any path portions of filename.  This
 | ||||
|    * prevents the next search from considering that part. */ | ||||
|   char const * result = LAST_SLASH(pathname); | ||||
|   if (!result) | ||||
|     result = pathname; | ||||
| 
 | ||||
|   /* Now look for an filename extension */ | ||||
|   result = strrchr(result, '.'); | ||||
|   if (result) | ||||
|     ++result; | ||||
|   return result; | ||||
| } | ||||
| 
 | ||||
| lsx_enum_item const * lsx_find_enum_text(char const * text, lsx_enum_item const * enum_items, int flags) | ||||
| { | ||||
|   lsx_enum_item const * result = NULL; /* Assume not found */ | ||||
|   sox_bool sensitive = !!(flags & lsx_find_enum_item_case_sensitive); | ||||
| 
 | ||||
|   while (enum_items->text) { | ||||
|     if ((!sensitive && !strcasecmp(text, enum_items->text)) || | ||||
|         ( sensitive && !    strcmp(text, enum_items->text))) | ||||
|       return enum_items;    /* Found exact match */ | ||||
|     if ((!sensitive && !strncasecmp(text, enum_items->text, strlen(text))) || | ||||
|         ( sensitive && !    strncmp(text, enum_items->text, strlen(text)))) { | ||||
|       if (result != NULL && result->value != enum_items->value) | ||||
|         return NULL;        /* Found ambiguity */ | ||||
|       result = enum_items;  /* Found sub-string match */ | ||||
|     } | ||||
|     ++enum_items; | ||||
|   } | ||||
|   return result; | ||||
| } | ||||
| 
 | ||||
| lsx_enum_item const * lsx_find_enum_value(unsigned value, lsx_enum_item const * enum_items) | ||||
| { | ||||
|   for (;enum_items->text; ++enum_items) | ||||
|     if (value == enum_items->value) | ||||
|       return enum_items; | ||||
|   return NULL; | ||||
| } | ||||
| 
 | ||||
| int lsx_enum_option(int c, char const * arg, lsx_enum_item const * items) | ||||
| { | ||||
|   lsx_enum_item const * p = lsx_find_enum_text(arg, items, sox_false); | ||||
|   if (p == NULL) { | ||||
|     size_t len = 1; | ||||
|     char * set = lsx_malloc(len); | ||||
|     *set = 0; | ||||
|     for (p = items; p->text; ++p) { | ||||
|       set = lsx_realloc(set, len += 2 + strlen(p->text)); | ||||
|       strcat(set, ", "); strcat(set, p->text); | ||||
|     } | ||||
|     lsx_fail("-%c: `%s' is not one of: %s.", c, arg, set + 2); | ||||
|     free(set); | ||||
|     return INT_MAX; | ||||
|   } | ||||
|   return p->value; | ||||
| } | ||||
| 
 | ||||
| char const * lsx_sigfigs3(double number) | ||||
| { | ||||
|   static char const symbols[] = "\0kMGTPEZY"; | ||||
|   static char string[16][10];   /* FIXME: not thread-safe */ | ||||
|   static unsigned n;            /* ditto */ | ||||
|   unsigned a, b, c; | ||||
|   sprintf(string[n = (n+1) & 15], "%#.3g", number); | ||||
|   switch (sscanf(string[n], "%u.%ue%u", &a, &b, &c)) { | ||||
|     case 2: if (b) return string[n]; /* Can fall through */ | ||||
|     case 1: c = 2; break; | ||||
|     case 3: a = 100*a + b; break; | ||||
|   } | ||||
|   if (c < array_length(symbols) * 3 - 3) switch (c%3) { | ||||
|     case 0: sprintf(string[n], "%u.%02u%c", a/100,a%100, symbols[c/3]); break; | ||||
|     case 1: sprintf(string[n], "%u.%u%c"  , a/10 ,a%10 , symbols[c/3]); break; | ||||
|     case 2: sprintf(string[n], "%u%c"     , a          , symbols[c/3]); break; | ||||
|   } | ||||
|   return string[n]; | ||||
| } | ||||
| 
 | ||||
| char const * lsx_sigfigs3p(double percentage) | ||||
| { | ||||
|   static char string[16][10]; | ||||
|   static unsigned n; | ||||
|   sprintf(string[n = (n+1) & 15], "%.1f%%", percentage); | ||||
|   if (strlen(string[n]) < 5) | ||||
|     sprintf(string[n], "%.2f%%", percentage); | ||||
|   else if (strlen(string[n]) > 5) | ||||
|     sprintf(string[n], "%.0f%%", percentage); | ||||
|   return string[n]; | ||||
| } | ||||
| 
 | ||||
| int lsx_open_dllibrary( | ||||
|   int show_error_on_failure, | ||||
|   const char* library_description, | ||||
|   const char* const library_names[] UNUSED, | ||||
|   const lsx_dlfunction_info func_infos[], | ||||
|   lsx_dlptr selected_funcs[], | ||||
|   lsx_dlhandle* pdl) | ||||
| { | ||||
|   int failed = 0; | ||||
|   lsx_dlhandle dl = NULL; | ||||
| 
 | ||||
|   /* Track enough information to give a good error message about one failure.
 | ||||
|    * Let failed symbol load override failed library open, and let failed | ||||
|    * library open override missing static symbols. | ||||
|    */ | ||||
|   const char* failed_libname = NULL; | ||||
|   const char* failed_funcname = NULL; | ||||
| 
 | ||||
| #ifdef HAVE_LIBLTDL | ||||
|   if (library_names && library_names[0]) | ||||
|   { | ||||
|     const char* const* libname; | ||||
|     if (lt_dlinit()) | ||||
|     { | ||||
|       lsx_fail( | ||||
|         "Unable to load %s - failed to initialize ltdl.", | ||||
|         library_description); | ||||
|       return 1; | ||||
|     } | ||||
| 
 | ||||
|     for (libname = library_names; *libname; libname++) | ||||
|     { | ||||
|       lsx_debug("Attempting to open %s (%s).", library_description, *libname); | ||||
|       dl = lt_dlopenext(*libname); | ||||
|       if (dl) | ||||
|       { | ||||
|         size_t i; | ||||
|         lsx_debug("Opened %s (%s).", library_description, *libname); | ||||
|         for (i = 0; func_infos[i].name; i++) | ||||
|         { | ||||
|           union {lsx_dlptr fn; lt_ptr ptr;} func; | ||||
|           func.ptr = lt_dlsym(dl, func_infos[i].name); | ||||
|           selected_funcs[i] = func.fn ? func.fn : func_infos[i].stub_func; | ||||
|           if (!selected_funcs[i]) | ||||
|           { | ||||
|             lt_dlclose(dl); | ||||
|             dl = NULL; | ||||
|             failed_libname = *libname; | ||||
|             failed_funcname = func_infos[i].name; | ||||
|             lsx_debug("Cannot use %s (%s) - missing function \"%s\".", library_description, failed_libname, failed_funcname); | ||||
|             break; | ||||
|           } | ||||
|         } | ||||
| 
 | ||||
|         if (dl) | ||||
|           break; | ||||
|       } | ||||
|       else if (!failed_libname) | ||||
|       { | ||||
|         failed_libname = *libname; | ||||
|       } | ||||
|     } | ||||
| 
 | ||||
|     if (!dl) | ||||
|       lt_dlexit(); | ||||
|   } | ||||
| #endif /* HAVE_LIBLTDL */ | ||||
| 
 | ||||
|   if (!dl) | ||||
|   { | ||||
|     size_t i; | ||||
|     for (i = 0; func_infos[i].name; i++) | ||||
|     { | ||||
|       selected_funcs[i] = | ||||
|           func_infos[i].static_func | ||||
|           ? func_infos[i].static_func | ||||
|           : func_infos[i].stub_func; | ||||
|       if (!selected_funcs[i]) | ||||
|       { | ||||
|         if (!failed_libname) | ||||
|         { | ||||
|           failed_libname = "static"; | ||||
|           failed_funcname = func_infos[i].name; | ||||
|         } | ||||
| 
 | ||||
|         failed = 1; | ||||
|         break; | ||||
|       } | ||||
|     } | ||||
|   } | ||||
| 
 | ||||
|   if (failed) | ||||
|   { | ||||
|     size_t i; | ||||
|     for (i = 0; func_infos[i].name; i++) | ||||
|       selected_funcs[i] = NULL; | ||||
| #ifdef HAVE_LIBLTDL | ||||
| #define LTDL_MISSING "" | ||||
| #else | ||||
| #define LTDL_MISSING " (Dynamic library support not configured.)" | ||||
| #endif /* HAVE_LIBLTDL */ | ||||
|     if (failed_funcname) | ||||
|     { | ||||
|       if (show_error_on_failure) | ||||
|         lsx_fail( | ||||
|           "Unable to load %s (%s) function \"%s\"." LTDL_MISSING, | ||||
|           library_description, | ||||
|           failed_libname, | ||||
|           failed_funcname); | ||||
|       else | ||||
|         lsx_report( | ||||
|           "Unable to load %s (%s) function \"%s\"." LTDL_MISSING, | ||||
|           library_description, | ||||
|           failed_libname, | ||||
|           failed_funcname); | ||||
|     } | ||||
|     else if (failed_libname) | ||||
|     { | ||||
|       if (show_error_on_failure) | ||||
|         lsx_fail( | ||||
|           "Unable to load %s (%s)." LTDL_MISSING, | ||||
|           library_description, | ||||
|           failed_libname); | ||||
|       else | ||||
|         lsx_report( | ||||
|           "Unable to load %s (%s)." LTDL_MISSING, | ||||
|           library_description, | ||||
|           failed_libname); | ||||
|     } | ||||
|     else | ||||
|     { | ||||
|       if (show_error_on_failure) | ||||
|         lsx_fail( | ||||
|           "Unable to load %s - no dynamic library names selected." LTDL_MISSING, | ||||
|           library_description); | ||||
|       else | ||||
|         lsx_report( | ||||
|           "Unable to load %s - no dynamic library names selected." LTDL_MISSING, | ||||
|           library_description); | ||||
|     } | ||||
|   } | ||||
| 
 | ||||
|   *pdl = dl; | ||||
|   return failed; | ||||
| } | ||||
| 
 | ||||
| void lsx_close_dllibrary( | ||||
|   lsx_dlhandle dl UNUSED) | ||||
| { | ||||
| #ifdef HAVE_LIBLTDL | ||||
|   if (dl) | ||||
|   { | ||||
|     lt_dlclose(dl); | ||||
|     lt_dlexit(); | ||||
|   } | ||||
| #endif /* HAVE_LIBLTDL */ | ||||
| } | ||||
| @ -1,184 +0,0 @@ | ||||
| /* General purpose, i.e. non SoX specific, utility functions and macros.
 | ||||
|  * | ||||
|  * (c) 2006-8 Chris Bagwell and SoX contributors | ||||
|  * | ||||
|  * This library is free software; you can redistribute it and/or modify it | ||||
|  * under the terms of the GNU Lesser General Public License as published by | ||||
|  * the Free Software Foundation; either version 2.1 of the License, or (at | ||||
|  * your option) any later version. | ||||
|  * | ||||
|  * This library is distributed in the hope that it will be useful, but | ||||
|  * WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser | ||||
|  * General Public License for more details. | ||||
|  * | ||||
|  * You should have received a copy of the GNU Lesser General Public License | ||||
|  * along with this library; if not, write to the Free Software Foundation, | ||||
|  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA | ||||
|  */ | ||||
| 
 | ||||
| #include <stdio.h> | ||||
| #include <stdlib.h> | ||||
| #include <inttypes.h> | ||||
| #include "soxconfig.h" | ||||
| 
 | ||||
| #ifdef HAVE_SYS_TYPES_H | ||||
| #include <sys/types.h> /* For off_t not found in stdio.h */ | ||||
| #endif | ||||
| 
 | ||||
| #ifdef HAVE_SYS_STAT_H | ||||
| #include <sys/stat.h> /* Needs to be included before we redefine off_t. */ | ||||
| #endif | ||||
| 
 | ||||
| #include "xmalloc.h" | ||||
| 
 | ||||
| /*---------------------------- Portability stuff -----------------------------*/ | ||||
| 
 | ||||
| #ifdef __GNUC__ | ||||
| #define NORET __attribute__((noreturn)) | ||||
| #define UNUSED __attribute__ ((unused)) | ||||
| #else | ||||
| #define NORET | ||||
| #define UNUSED | ||||
| #endif | ||||
| 
 | ||||
| #ifdef _MSC_VER | ||||
| 
 | ||||
| #define __STDC__ 1 | ||||
| #define O_BINARY _O_BINARY | ||||
| #define O_CREAT _O_CREAT | ||||
| #define O_RDWR _O_RDWR | ||||
| #define O_TRUNC _O_TRUNC | ||||
| #define S_IFMT _S_IFMT | ||||
| #define S_IFREG _S_IFREG | ||||
| #define S_IREAD _S_IREAD | ||||
| #define S_IWRITE _S_IWRITE | ||||
| #define close _close | ||||
| #define dup _dup | ||||
| #define fdopen _fdopen | ||||
| #define fileno _fileno | ||||
| 
 | ||||
| #ifdef _fstati64 | ||||
| #define fstat _fstati64 | ||||
| #else | ||||
| #define fstat _fstat | ||||
| #endif | ||||
| 
 | ||||
| #define ftime _ftime | ||||
| #define inline __inline | ||||
| #define isatty _isatty | ||||
| #define kbhit _kbhit | ||||
| #define mktemp _mktemp | ||||
| #define off_t _off_t | ||||
| #define open _open | ||||
| #define pclose _pclose | ||||
| #define popen _popen | ||||
| #define setmode _setmode | ||||
| #define snprintf _snprintf | ||||
| 
 | ||||
| #ifdef _stati64 | ||||
| #define stat _stati64 | ||||
| #else | ||||
| #define stat _stat | ||||
| #endif | ||||
| 
 | ||||
| #define strdup _strdup | ||||
| #define timeb _timeb | ||||
| #define unlink _unlink | ||||
| 
 | ||||
| #if defined(HAVE__FSEEKI64) && !defined(HAVE_FSEEKO) | ||||
| #undef off_t | ||||
| #define fseeko _fseeki64 | ||||
| #define ftello _ftelli64 | ||||
| #define off_t __int64 | ||||
| #define HAVE_FSEEKO 1 | ||||
| #endif | ||||
| 
 | ||||
| #elif defined(__MINGW32__) | ||||
| 
 | ||||
| #if !defined(HAVE_FSEEKO) | ||||
| #undef off_t | ||||
| #define fseeko fseeko64 | ||||
| #define fstat _fstati64 | ||||
| #define ftello ftello64 | ||||
| #define off_t off64_t | ||||
| #define stat _stati64 | ||||
| #define HAVE_FSEEKO 1 | ||||
| #endif | ||||
| 
 | ||||
| #endif | ||||
| 
 | ||||
| #if defined(DOS) || defined(WIN32) || defined(__NT__) || defined(__DJGPP__) || defined(__OS2__) | ||||
|   #define LAST_SLASH(path) max(strrchr(path, '/'), strrchr(path, '\\')) | ||||
|   #define IS_ABSOLUTE(path) ((path)[0] == '/' || (path)[0] == '\\' || (path)[1] == ':') | ||||
|   #define SET_BINARY_MODE(file) setmode(fileno(file), O_BINARY) | ||||
|   #define POPEN_MODE "rb" | ||||
| #else | ||||
|   #define LAST_SLASH(path) strrchr(path, '/') | ||||
|   #define IS_ABSOLUTE(path) ((path)[0] == '/') | ||||
|   #define SET_BINARY_MODE(file) | ||||
| #endif | ||||
| 
 | ||||
| #ifdef WORDS_BIGENDIAN | ||||
|   #define MACHINE_IS_BIGENDIAN 1 | ||||
|   #define MACHINE_IS_LITTLEENDIAN 0 | ||||
| #else | ||||
|   #define MACHINE_IS_BIGENDIAN 0 | ||||
|   #define MACHINE_IS_LITTLEENDIAN 1 | ||||
| #endif | ||||
| 
 | ||||
| /*--------------------------- Language extensions ----------------------------*/ | ||||
| 
 | ||||
| /* Compile-time ("static") assertion */ | ||||
| /*   e.g. assert_static(sizeof(int) >= 4, int_type_too_small)    */ | ||||
| #define assert_static(e,f) enum {assert_static__##f = 1/(e)} | ||||
| #define array_length(a) (sizeof(a)/sizeof(a[0])) | ||||
| #define field_offset(type, field) ((size_t)&(((type *)0)->field)) | ||||
| #define unless(x) if (!(x)) | ||||
| 
 | ||||
| /*------------------------------- Maths stuff --------------------------------*/ | ||||
| 
 | ||||
| #include <math.h> | ||||
| 
 | ||||
| #ifdef min | ||||
| #undef min | ||||
| #endif | ||||
| #define min(a, b) ((a) <= (b) ? (a) : (b)) | ||||
| 
 | ||||
| #ifdef max | ||||
| #undef max | ||||
| #endif | ||||
| #define max(a, b) ((a) >= (b) ? (a) : (b)) | ||||
| 
 | ||||
| #define range_limit(x, lower, upper) (min(max(x, lower), upper)) | ||||
| 
 | ||||
| #ifndef M_PI | ||||
| #define M_PI    3.14159265358979323846 | ||||
| #endif | ||||
| #ifndef M_PI_2 | ||||
| #define M_PI_2  1.57079632679489661923  /* pi/2 */ | ||||
| #endif | ||||
| #ifndef M_LN10 | ||||
| #define M_LN10  2.30258509299404568402  /* natural log of 10 */ | ||||
| #endif | ||||
| #ifndef M_SQRT2 | ||||
| #define M_SQRT2  sqrt(2.) | ||||
| #endif | ||||
| 
 | ||||
| #define sqr(a) ((a) * (a)) | ||||
| #define sign(x) ((x) < 0? -1 : 1) | ||||
| 
 | ||||
| /* Numerical Recipes in C, p. 284 */ | ||||
| #define ranqd1(x) ((x) = 1664525L * (x) + 1013904223L) /* int32_t x */ | ||||
| #define dranqd1(x) (ranqd1(x) * (1. / (65536. * 32768.))) /* [-1,1) */ | ||||
| 
 | ||||
| #define dB_to_linear(x) exp((x) * M_LN10 * 0.05) | ||||
| #define linear_to_dB(x) (log10(x) * 20) | ||||
| 
 | ||||
| extern int lsx_strcasecmp(const char *s1, const char *st); | ||||
| extern int lsx_strncasecmp(char const *s1, char const *s2, size_t n); | ||||
| 
 | ||||
| #ifndef HAVE_STRCASECMP | ||||
| #define strcasecmp(s1, s2) lsx_strcasecmp((s1), (s2)) | ||||
| #define strncasecmp(s1, s2, n) lsx_strncasecmp((s1), (s2), (n)) | ||||
| #endif | ||||
| @ -1,329 +0,0 @@ | ||||
| /* libSoX effect: Voice Activity Detector  (c) 2009 robs@users.sourceforge.net
 | ||||
|  * | ||||
|  * This library is free software; you can redistribute it and/or modify it | ||||
|  * under the terms of the GNU Lesser General Public License as published by | ||||
|  * the Free Software Foundation; either version 2.1 of the License, or (at | ||||
|  * your option) any later version. | ||||
|  * | ||||
|  * This library is distributed in the hope that it will be useful, but | ||||
|  * WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser | ||||
|  * General Public License for more details. | ||||
|  * | ||||
|  * You should have received a copy of the GNU Lesser General Public License | ||||
|  * along with this library; if not, write to the Free Software Foundation, | ||||
|  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA | ||||
|  */ | ||||
| 
 | ||||
| #include "sox_i.h" | ||||
| #include <string.h> | ||||
| 
 | ||||
| typedef struct { | ||||
|   double    * dftBuf, * noiseSpectrum, * spectrum, * measures, meanMeas; | ||||
| } chan_t; | ||||
| 
 | ||||
| typedef struct {                /* Configuration parameters: */ | ||||
|   double    bootTime, noiseTcUp, noiseTcDown, noiseReductionAmount; | ||||
|   double    measureFreq, measureDuration, measureTc, preTriggerTime; | ||||
|   double    hpFilterFreq, lpFilterFreq, hpLifterFreq, lpLifterFreq; | ||||
|   double    triggerTc, triggerLevel, searchTime, gapTime; | ||||
|                                 /* Working variables: */ | ||||
|   sox_sample_t  * samples; | ||||
|   unsigned  dftLen_ws, samplesLen_ns, samplesIndex_ns, flushedLen_ns, gapLen; | ||||
|   unsigned  measurePeriod_ns, measuresLen, measuresIndex; | ||||
|   unsigned  measureTimer_ns, measureLen_ws, measureLen_ns; | ||||
|   unsigned  spectrumStart, spectrumEnd, cepstrumStart, cepstrumEnd; /* bins */ | ||||
|   int       bootCountMax, bootCount; | ||||
|   double    noiseTcUpMult, noiseTcDownMult; | ||||
|   double    measureTcMult, triggerMeasTcMult; | ||||
|   double    * spectrumWindow, * cepstrumWindow; | ||||
|   chan_t    * channels; | ||||
| } priv_t; | ||||
| 
 | ||||
| #define GETOPT_FREQ(optstate, c, name, min) \ | ||||
|     case c: p->name = lsx_parse_frequency(optstate.arg, &parseIndex); \
 | ||||
|       if (p->name < min || *parseIndex) return lsx_usage(effp); \
 | ||||
|       break; | ||||
| 
 | ||||
| static int create(sox_effect_t * effp, int argc, char * * argv) | ||||
| { | ||||
|   priv_t * p = (priv_t *)effp->priv; | ||||
|   #define opt_str "+b:N:n:r:f:m:M:h:l:H:L:T:t:s:g:p:" | ||||
|   int c; | ||||
|   lsx_getopt_t optstate; | ||||
|   lsx_getopt_init(argc, argv, opt_str, NULL, lsx_getopt_flag_none, 1, &optstate); | ||||
| 
 | ||||
|   p->bootTime        = .35; | ||||
|   p->noiseTcUp       = .1; | ||||
|   p->noiseTcDown     = .01; | ||||
|   p->noiseReductionAmount = 1.35; | ||||
| 
 | ||||
|   p->measureFreq     = 20; | ||||
|   p->measureDuration = 2 / p->measureFreq; /* 50% overlap */ | ||||
|   p->measureTc       = .4; | ||||
| 
 | ||||
|   p->hpFilterFreq    = 50; | ||||
|   p->lpFilterFreq    = 6000; | ||||
|   p->hpLifterFreq    = 150; | ||||
|   p->lpLifterFreq    = 2000; | ||||
| 
 | ||||
|   p->triggerTc       = .25; | ||||
|   p->triggerLevel    = 7; | ||||
| 
 | ||||
|   p->searchTime      = 1; | ||||
|   p->gapTime         = .25; | ||||
| 
 | ||||
|   while ((c = lsx_getopt(&optstate)) != -1) switch (c) { | ||||
|     char * parseIndex; | ||||
|     GETOPT_NUMERIC(optstate, 'b', bootTime      ,  .1 , 10) | ||||
|     GETOPT_NUMERIC(optstate, 'N', noiseTcUp     ,  .1 , 10) | ||||
|     GETOPT_NUMERIC(optstate, 'n', noiseTcDown   ,.001 , .1) | ||||
|     GETOPT_NUMERIC(optstate, 'r', noiseReductionAmount,0 , 2) | ||||
|     GETOPT_NUMERIC(optstate, 'f', measureFreq   ,   5 , 50) | ||||
|     GETOPT_NUMERIC(optstate, 'm', measureDuration, .01 , 1) | ||||
|     GETOPT_NUMERIC(optstate, 'M', measureTc     ,  .1 , 1) | ||||
|     GETOPT_FREQ(   optstate, 'h', hpFilterFreq  ,  10) | ||||
|     GETOPT_FREQ(   optstate, 'l', lpFilterFreq  ,  1000) | ||||
|     GETOPT_FREQ(   optstate, 'H', hpLifterFreq  ,  10) | ||||
|     GETOPT_FREQ(   optstate, 'L', lpLifterFreq  ,  1000) | ||||
|     GETOPT_NUMERIC(optstate, 'T', triggerTc     , .01 , 1) | ||||
|     GETOPT_NUMERIC(optstate, 't', triggerLevel  ,   0 , 20) | ||||
|     GETOPT_NUMERIC(optstate, 's', searchTime    ,  .1 , 4) | ||||
|     GETOPT_NUMERIC(optstate, 'g', gapTime       ,  .1 , 1) | ||||
|     GETOPT_NUMERIC(optstate, 'p', preTriggerTime,   0 , 4) | ||||
|     default: lsx_fail("invalid option `-%c'", optstate.opt); return lsx_usage(effp); | ||||
|   } | ||||
|   return optstate.ind !=argc? lsx_usage(effp) : SOX_SUCCESS; | ||||
| } | ||||
| 
 | ||||
| static int start(sox_effect_t * effp) | ||||
| { | ||||
|   priv_t * p = (priv_t *)effp->priv; | ||||
|   unsigned i, fixedPreTriggerLen_ns, searchPreTriggerLen_ns; | ||||
| 
 | ||||
|   fixedPreTriggerLen_ns = p->preTriggerTime * effp->in_signal.rate + .5; | ||||
|   fixedPreTriggerLen_ns *= effp->in_signal.channels; | ||||
| 
 | ||||
|   p->measureLen_ws = effp->in_signal.rate * p->measureDuration + .5; | ||||
|   p->measureLen_ns = p->measureLen_ws * effp->in_signal.channels; | ||||
|   for (p->dftLen_ws = 16; p->dftLen_ws < p->measureLen_ws; p->dftLen_ws <<= 1); | ||||
|   lsx_debug("dftLen_ws=%u measureLen_ws=%u", p->dftLen_ws, p->measureLen_ws); | ||||
| 
 | ||||
|   p->measurePeriod_ns = effp->in_signal.rate / p->measureFreq + .5; | ||||
|   p->measurePeriod_ns *= effp->in_signal.channels; | ||||
|   p->measuresLen = ceil(p->searchTime * p->measureFreq); | ||||
|   searchPreTriggerLen_ns = p->measuresLen * p->measurePeriod_ns; | ||||
|   p->gapLen = p->gapTime * p->measureFreq + .5; | ||||
| 
 | ||||
|   p->samplesLen_ns = | ||||
|     fixedPreTriggerLen_ns + searchPreTriggerLen_ns + p->measureLen_ns; | ||||
|   lsx_Calloc(p->samples, p->samplesLen_ns); | ||||
| 
 | ||||
|   lsx_Calloc(p->channels, effp->in_signal.channels); | ||||
|   for (i = 0; i < effp->in_signal.channels; ++i) { | ||||
|     chan_t * c = &p->channels[i]; | ||||
|     lsx_Calloc(c->dftBuf, p->dftLen_ws); | ||||
|     lsx_Calloc(c->spectrum, p->dftLen_ws); | ||||
|     lsx_Calloc(c->noiseSpectrum, p->dftLen_ws); | ||||
|     lsx_Calloc(c->measures, p->measuresLen); | ||||
|   } | ||||
| 
 | ||||
|   lsx_Calloc(p->spectrumWindow, p->measureLen_ws); | ||||
|   for (i = 0; i < p->measureLen_ws; ++i) | ||||
|     p->spectrumWindow[i] = -2./ SOX_SAMPLE_MIN / sqrt((double)p->measureLen_ws); | ||||
|   lsx_apply_hann(p->spectrumWindow, (int)p->measureLen_ws); | ||||
| 
 | ||||
|   p->spectrumStart = p->hpFilterFreq / effp->in_signal.rate * p->dftLen_ws + .5; | ||||
|   p->spectrumStart = max(p->spectrumStart, 1); | ||||
|   p->spectrumEnd = p->lpFilterFreq / effp->in_signal.rate * p->dftLen_ws + .5; | ||||
|   p->spectrumEnd = min(p->spectrumEnd, p->dftLen_ws / 2); | ||||
| 
 | ||||
|   lsx_Calloc(p->cepstrumWindow, p->spectrumEnd - p->spectrumStart); | ||||
|   for (i = 0; i < p->spectrumEnd - p->spectrumStart; ++i) | ||||
|     p->cepstrumWindow[i] = 2 / sqrt((double)p->spectrumEnd - p->spectrumStart); | ||||
|   lsx_apply_hann(p->cepstrumWindow,(int)(p->spectrumEnd - p->spectrumStart)); | ||||
| 
 | ||||
|   p->cepstrumStart = ceil(effp->in_signal.rate * .5 / p->lpLifterFreq); | ||||
|   p->cepstrumEnd  = floor(effp->in_signal.rate * .5 / p->hpLifterFreq); | ||||
|   p->cepstrumEnd = min(p->cepstrumEnd, p->dftLen_ws / 4); | ||||
|   if (p->cepstrumEnd <= p->cepstrumStart) | ||||
|     return SOX_EOF; | ||||
| 
 | ||||
|   p->noiseTcUpMult     = exp(-1 / (p->noiseTcUp   * p->measureFreq)); | ||||
|   p->noiseTcDownMult   = exp(-1 / (p->noiseTcDown * p->measureFreq)); | ||||
|   p->measureTcMult     = exp(-1 / (p->measureTc   * p->measureFreq)); | ||||
|   p->triggerMeasTcMult = exp(-1 / (p->triggerTc   * p->measureFreq)); | ||||
| 
 | ||||
|   p->bootCountMax = p->bootTime * p->measureFreq - .5; | ||||
|   p->measureTimer_ns = p->measureLen_ns; | ||||
|   p->bootCount = p->measuresIndex = p->flushedLen_ns = p->samplesIndex_ns = 0; | ||||
| 
 | ||||
|   effp->out_signal.length = SOX_UNKNOWN_LEN; /* depends on input data */ | ||||
|   return SOX_SUCCESS; | ||||
| } | ||||
| 
 | ||||
| static int flowFlush(sox_effect_t * effp, sox_sample_t const * ibuf, | ||||
|     sox_sample_t * obuf, size_t * ilen, size_t * olen) | ||||
| { | ||||
|   priv_t * p = (priv_t *)effp->priv; | ||||
|   size_t odone = min(p->samplesLen_ns - p->flushedLen_ns, *olen); | ||||
|   size_t odone1 = min(odone, p->samplesLen_ns - p->samplesIndex_ns); | ||||
| 
 | ||||
|   memcpy(obuf, p->samples + p->samplesIndex_ns, odone1 * sizeof(*obuf)); | ||||
|   if ((p->samplesIndex_ns += odone1) == p->samplesLen_ns) { | ||||
|     memcpy(obuf + odone1, p->samples, (odone - odone1) * sizeof(*obuf)); | ||||
|     p->samplesIndex_ns = odone - odone1; | ||||
|   } | ||||
|   if ((p->flushedLen_ns += odone) == p->samplesLen_ns) { | ||||
|     size_t olen1 = *olen - odone; | ||||
|     (effp->handler.flow = lsx_flow_copy)(effp, ibuf, obuf +odone, ilen, &olen1); | ||||
|     odone += olen1; | ||||
|   } | ||||
|   else *ilen = 0; | ||||
|   *olen = odone; | ||||
|   return SOX_SUCCESS; | ||||
| } | ||||
| 
 | ||||
| static double measure( | ||||
|     priv_t * p, chan_t * c, size_t index_ns, unsigned step_ns, int bootCount) | ||||
| { | ||||
|   double mult, result = 0; | ||||
|   size_t i; | ||||
| 
 | ||||
|   for (i = 0; i < p->measureLen_ws; ++i, index_ns = (index_ns + step_ns) % p->samplesLen_ns) | ||||
|     c->dftBuf[i] = p->samples[index_ns] * p->spectrumWindow[i]; | ||||
|   memset(c->dftBuf + i, 0, (p->dftLen_ws - i) * sizeof(*c->dftBuf)); | ||||
|   lsx_safe_rdft((int)p->dftLen_ws, 1, c->dftBuf); | ||||
| 
 | ||||
|   memset(c->dftBuf, 0, p->spectrumStart * sizeof(*c->dftBuf)); | ||||
|   for (i = p->spectrumStart; i < p->spectrumEnd; ++i) { | ||||
|     double d = sqrt(sqr(c->dftBuf[2 * i]) + sqr(c->dftBuf[2 * i + 1])); | ||||
|     mult = bootCount >= 0? bootCount / (1. + bootCount) : p->measureTcMult; | ||||
|     c->spectrum[i] = c->spectrum[i] * mult + d * (1 - mult); | ||||
|     d = sqr(c->spectrum[i]); | ||||
|     mult = bootCount >= 0? 0 : | ||||
|         d > c->noiseSpectrum[i]? p->noiseTcUpMult : p->noiseTcDownMult; | ||||
|     c->noiseSpectrum[i] = c->noiseSpectrum[i] * mult + d * (1 - mult); | ||||
|     d = sqrt(max(0, d - p->noiseReductionAmount * c->noiseSpectrum[i])); | ||||
|     c->dftBuf[i] = d * p->cepstrumWindow[i - p->spectrumStart]; | ||||
|   } | ||||
|   memset(c->dftBuf + i, 0, ((p->dftLen_ws >> 1) - i) * sizeof(*c->dftBuf)); | ||||
|   lsx_safe_rdft((int)p->dftLen_ws >> 1, 1, c->dftBuf); | ||||
| 
 | ||||
|   for (i = p->cepstrumStart; i < p->cepstrumEnd; ++i) | ||||
|     result += sqr(c->dftBuf[2 * i]) + sqr(c->dftBuf[2 * i + 1]); | ||||
|   result = log(result / (p->cepstrumEnd - p->cepstrumStart)); | ||||
|   return max(0, 21 + result); | ||||
| } | ||||
| 
 | ||||
| static int flowTrigger(sox_effect_t * effp, sox_sample_t const * ibuf, | ||||
|     sox_sample_t * obuf, size_t * ilen, size_t * olen) | ||||
| { | ||||
|   priv_t * p = (priv_t *)effp->priv; | ||||
|   sox_bool hasTriggered = sox_false; | ||||
|   size_t i, idone = 0, numMeasuresToFlush = 0; | ||||
| 
 | ||||
|   while (idone < *ilen && !hasTriggered) { | ||||
|     p->measureTimer_ns -= effp->in_signal.channels; | ||||
|     for (i = 0; i < effp->in_signal.channels; ++i, ++idone) { | ||||
|       chan_t * c = &p->channels[i]; | ||||
|       p->samples[p->samplesIndex_ns++] = *ibuf++; | ||||
|       if (!p->measureTimer_ns) { | ||||
|         size_t x = (p->samplesIndex_ns + p->samplesLen_ns - p->measureLen_ns) % p->samplesLen_ns; | ||||
|         double meas = measure(p, c, x, effp->in_signal.channels, p->bootCount); | ||||
|         c->measures[p->measuresIndex] = meas; | ||||
|         c->meanMeas = c->meanMeas * p->triggerMeasTcMult + | ||||
|             meas *(1 - p->triggerMeasTcMult); | ||||
| 
 | ||||
|         if (hasTriggered |= c->meanMeas >= p->triggerLevel) { | ||||
|           unsigned n = p->measuresLen, k = p->measuresIndex; | ||||
|           unsigned j, jTrigger = n, jZero = n; | ||||
|           for (j = 0; j < n; ++j, k = (k + n - 1) % n) | ||||
|             if (c->measures[k] >= p->triggerLevel && j <= jTrigger + p->gapLen) | ||||
|               jZero = jTrigger = j; | ||||
|             else if (!c->measures[k] && jTrigger >= jZero) | ||||
|               jZero = j; | ||||
|           j = min(j, jZero); | ||||
|           numMeasuresToFlush = range_limit(j, numMeasuresToFlush, n); | ||||
|         } | ||||
|         lsx_debug_more("%12g %12g %u", | ||||
|             meas, c->meanMeas, (unsigned)numMeasuresToFlush); | ||||
|       } | ||||
|     } | ||||
|     if (p->samplesIndex_ns == p->samplesLen_ns) | ||||
|       p->samplesIndex_ns = 0; | ||||
|     if (!p->measureTimer_ns) { | ||||
|       p->measureTimer_ns = p->measurePeriod_ns; | ||||
|       ++p->measuresIndex; | ||||
|       p->measuresIndex %= p->measuresLen; | ||||
|       if (p->bootCount >= 0) | ||||
|         p->bootCount = p->bootCount == p->bootCountMax? -1 : p->bootCount + 1; | ||||
|     } | ||||
|   } | ||||
|   if (hasTriggered) { | ||||
|     size_t ilen1 = *ilen - idone; | ||||
|     p->flushedLen_ns = (p->measuresLen - numMeasuresToFlush) * p->measurePeriod_ns; | ||||
|     p->samplesIndex_ns = (p->samplesIndex_ns + p->flushedLen_ns) % p->samplesLen_ns; | ||||
|     (effp->handler.flow = flowFlush)(effp, ibuf, obuf, &ilen1, olen); | ||||
|     idone += ilen1; | ||||
|   } | ||||
|   else *olen = 0; | ||||
|   *ilen = idone; | ||||
|   return SOX_SUCCESS; | ||||
| } | ||||
| 
 | ||||
| static int drain(sox_effect_t * effp, sox_sample_t * obuf, size_t * olen) | ||||
| { | ||||
|   size_t ilen = 0; | ||||
|   return effp->handler.flow(effp, NULL, obuf, &ilen, olen); | ||||
| } | ||||
| 
 | ||||
| static int stop(sox_effect_t * effp) | ||||
| { | ||||
|   priv_t * p = (priv_t *)effp->priv; | ||||
|   unsigned i; | ||||
| 
 | ||||
|   for (i = 0; i < effp->in_signal.channels; ++i) { | ||||
|     chan_t * c = &p->channels[i]; | ||||
|     free(c->measures); | ||||
|     free(c->noiseSpectrum); | ||||
|     free(c->spectrum); | ||||
|     free(c->dftBuf); | ||||
|   } | ||||
|   free(p->channels); | ||||
|   free(p->cepstrumWindow); | ||||
|   free(p->spectrumWindow); | ||||
|   free(p->samples); | ||||
|   return SOX_SUCCESS; | ||||
| } | ||||
| 
 | ||||
| sox_effect_handler_t const * lsx_vad_effect_fn(void) | ||||
| { | ||||
|   static sox_effect_handler_t handler = {"vad", NULL, | ||||
|     SOX_EFF_MCHAN | SOX_EFF_LENGTH | SOX_EFF_MODIFY, | ||||
|     create, start, flowTrigger, drain, stop, NULL, sizeof(priv_t) | ||||
|   }; | ||||
|   static char const * lines[] = { | ||||
|     "[options]", | ||||
|     "\t-t trigger-level                (7)", | ||||
|     "\t-T trigger-time-constant        (0.25 s)", | ||||
|     "\t-s search-time                  (1 s)", | ||||
|     "\t-g allowed-gap                  (0.25 s)", | ||||
|     "\t-p pre-trigger-time             (0 s)", | ||||
|     "Advanced options:", | ||||
|     "\t-b noise-est-boot-time          (0.35 s)", | ||||
|     "\t-N noise-est-time-constant-up   (0.1 s)", | ||||
|     "\t-n noise-est-time-constant-down (0.01 s)", | ||||
|     "\t-r noise-reduction-amount       (1.35)", | ||||
|     "\t-f measurement-frequency        (20 Hz)", | ||||
|     "\t-m measurement-duration         (0.1 s)", | ||||
|     "\t-M measurement-time-constant    (0.4 s)", | ||||
|     "\t-h high-pass-filter             (50 Hz)", | ||||
|     "\t-l low-pass-filter              (6000 Hz)", | ||||
|     "\t-H high-pass-lifter             (150 Hz)", | ||||
|     "\t-L low-pass-lifter              (2000 Hz)", | ||||
|   }; | ||||
|   static char * usage; | ||||
|   handler.usage = lsx_usage_lines(&usage, lines, array_length(lines)); | ||||
|   return &handler; | ||||
| } | ||||
| @ -1,184 +0,0 @@ | ||||
| /* Copyright (c) 20/03/2000 Fabien COELHO <fabien@coelho.net>
 | ||||
|  * Copyright (c) 2000-2007 SoX contributors | ||||
|  * | ||||
|  * SoX vol effect; change volume with basic linear amplitude formula. | ||||
|  * Beware of saturations!  Clipping is checked and reported. | ||||
|  * | ||||
|  * FIXME: deprecate or remove the limiter in favour of compand. | ||||
|  */ | ||||
| #define vol_usage \ | ||||
|   "GAIN [TYPE [LIMITERGAIN]]\n" \
 | ||||
|   "\t(default TYPE=amplitude: 1 is constant, < 0 change phase;\n" \
 | ||||
|   "\tTYPE=power 1 is constant; TYPE=dB: 0 is constant, +6 doubles ampl.)\n" \
 | ||||
|   "\tThe peak limiter has a gain much less than 1 (e.g. 0.05 or 0.02) and\n" \
 | ||||
|   "\tis only used on peaks (to prevent clipping); default is no limiter." | ||||
| 
 | ||||
| #include "sox_i.h" | ||||
| 
 | ||||
| typedef struct { | ||||
|   double    gain; /* amplitude gain. */ | ||||
|   sox_bool  uselimiter; | ||||
|   double    limiterthreshhold; | ||||
|   double    limitergain; | ||||
|   uint64_t  limited; /* number of limited values to report. */ | ||||
|   uint64_t  totalprocessed; | ||||
| } priv_t; | ||||
| 
 | ||||
| enum {vol_amplitude, vol_dB, vol_power}; | ||||
| 
 | ||||
| static lsx_enum_item const vol_types[] = { | ||||
|   LSX_ENUM_ITEM(vol_,amplitude) | ||||
|   LSX_ENUM_ITEM(vol_,dB) | ||||
|   LSX_ENUM_ITEM(vol_,power) | ||||
|   {0, 0}}; | ||||
| 
 | ||||
| /*
 | ||||
|  * Process options: gain (float) type (amplitude, power, dB) | ||||
|  */ | ||||
| static int getopts(sox_effect_t * effp, int argc, char **argv) | ||||
| { | ||||
|   priv_t *     vol = (priv_t *) effp->priv; | ||||
|   char      type_string[11]; | ||||
|   char *    type_ptr = type_string; | ||||
|   char      dummy;             /* To check for extraneous chars. */ | ||||
|   sox_bool  have_type; | ||||
|   --argc, ++argv; | ||||
| 
 | ||||
|   vol->gain = 1;               /* Default is no change. */ | ||||
|   vol->uselimiter = sox_false; /* Default is no limiter. */ | ||||
| 
 | ||||
|   /* Get the vol, and the type if it's in the same arg. */ | ||||
|   if (!argc || (have_type = sscanf(argv[0], "%lf %10s %c", &vol->gain, type_string, &dummy) - 1) > 1) | ||||
|     return lsx_usage(effp); | ||||
|   ++argv, --argc; | ||||
| 
 | ||||
|   /* No type yet? Get it from the next arg: */ | ||||
|   if (!have_type && argc) { | ||||
|     have_type = sox_true; | ||||
|     type_ptr = *argv; | ||||
|     ++argv, --argc; | ||||
|   } | ||||
| 
 | ||||
|   if (have_type) { | ||||
|     lsx_enum_item const * p = lsx_find_enum_text(type_ptr, vol_types, 0); | ||||
|     if (!p) | ||||
|       return lsx_usage(effp); | ||||
|     switch (p->value) { | ||||
|       case vol_dB: vol->gain = dB_to_linear(vol->gain); break; | ||||
|       case vol_power: /* power to amplitude, keep phase change */ | ||||
|         vol->gain = vol->gain > 0 ? sqrt(vol->gain) : -sqrt(-vol->gain); | ||||
|         break; | ||||
|     } | ||||
|   } | ||||
| 
 | ||||
|   if (argc) { | ||||
|     if (fabs(vol->gain) < 1 || sscanf(*argv, "%lf %c", &vol->limitergain, &dummy) != 1 || vol->limitergain <= 0 || vol->limitergain >= 1) | ||||
|       return lsx_usage(effp); | ||||
| 
 | ||||
|     vol->uselimiter = sox_true; | ||||
|     /* The following equation is derived so that there is no
 | ||||
|      * discontinuity in output amplitudes */ | ||||
|     /* and a SOX_SAMPLE_MAX input always maps to a SOX_SAMPLE_MAX output
 | ||||
|      * when the limiter is activated. */ | ||||
|     /* (NOTE: There **WILL** be a discontinuity in the slope
 | ||||
|      * of the output amplitudes when using the limiter.) */ | ||||
|     vol->limiterthreshhold = SOX_SAMPLE_MAX * (1.0 - vol->limitergain) / (fabs(vol->gain) - vol->limitergain); | ||||
|   } | ||||
|   lsx_debug("mult=%g limit=%g", vol->gain, vol->limitergain); | ||||
|   return SOX_SUCCESS; | ||||
| } | ||||
| 
 | ||||
| /*
 | ||||
|  * Start processing | ||||
|  */ | ||||
| static int start(sox_effect_t * effp) | ||||
| { | ||||
|     priv_t * vol = (priv_t *) effp->priv; | ||||
| 
 | ||||
|     if (vol->gain == 1) | ||||
|       return SOX_EFF_NULL; | ||||
| 
 | ||||
|     vol->limited = 0; | ||||
|     vol->totalprocessed = 0; | ||||
| 
 | ||||
|     return SOX_SUCCESS; | ||||
| } | ||||
| 
 | ||||
| /*
 | ||||
|  * Process data. | ||||
|  */ | ||||
| static int flow(sox_effect_t * effp, const sox_sample_t *ibuf, sox_sample_t *obuf, | ||||
|                 size_t *isamp, size_t *osamp) | ||||
| { | ||||
|     priv_t * vol = (priv_t *) effp->priv; | ||||
|     register double gain = vol->gain; | ||||
|     register double limiterthreshhold = vol->limiterthreshhold; | ||||
|     register double sample; | ||||
|     register size_t len; | ||||
| 
 | ||||
|     len = min(*osamp, *isamp); | ||||
| 
 | ||||
|     /* report back dealt with amount. */ | ||||
|     *isamp = len; *osamp = len; | ||||
| 
 | ||||
|     if (vol->uselimiter) | ||||
|     { | ||||
|         vol->totalprocessed += len; | ||||
| 
 | ||||
|         for (;len>0; len--) | ||||
|             { | ||||
|                 sample = *ibuf++; | ||||
| 
 | ||||
|                 if (sample > limiterthreshhold) | ||||
|                 { | ||||
|                         sample =  (SOX_SAMPLE_MAX - vol->limitergain * (SOX_SAMPLE_MAX - sample)); | ||||
|                         vol->limited++; | ||||
|                 } | ||||
|                 else if (sample < -limiterthreshhold) | ||||
|                 { | ||||
|                         sample = -(SOX_SAMPLE_MAX - vol->limitergain * (SOX_SAMPLE_MAX + sample)); | ||||
|                         /* FIXME: MIN is (-MAX)-1 so need to make sure we
 | ||||
|                          * don't go over that.  Probably could do this | ||||
|                          * check inside the above equation but I didn't | ||||
|                          * think it thru. | ||||
|                          */ | ||||
|                         if (sample < SOX_SAMPLE_MIN) | ||||
|                             sample = SOX_SAMPLE_MIN; | ||||
|                         vol->limited++; | ||||
|                 } else | ||||
|                         sample = gain * sample; | ||||
| 
 | ||||
|                 SOX_SAMPLE_CLIP_COUNT(sample, effp->clips); | ||||
|                *obuf++ = sample; | ||||
|             } | ||||
|     } | ||||
|     else | ||||
|     { | ||||
|         /* quite basic, with clipping */ | ||||
|         for (;len>0; len--) | ||||
|         { | ||||
|                 sample = gain * *ibuf++; | ||||
|                 SOX_SAMPLE_CLIP_COUNT(sample, effp->clips); | ||||
|                 *obuf++ = sample; | ||||
|         } | ||||
|     } | ||||
|     return SOX_SUCCESS; | ||||
| } | ||||
| 
 | ||||
| static int stop(sox_effect_t * effp) | ||||
| { | ||||
|   priv_t * vol = (priv_t *) effp->priv; | ||||
|   if (vol->limited) { | ||||
|     lsx_warn("limited %" PRIu64 " values (%d percent).", | ||||
|          vol->limited, (int) (vol->limited * 100.0 / vol->totalprocessed)); | ||||
|   } | ||||
|   return SOX_SUCCESS; | ||||
| } | ||||
| 
 | ||||
| sox_effect_handler_t const * lsx_vol_effect_fn(void) | ||||
| { | ||||
|   static sox_effect_handler_t handler = { | ||||
|     "vol", vol_usage, SOX_EFF_MCHAN | SOX_EFF_GAIN, getopts, start, flow, 0, stop, 0, sizeof(priv_t) | ||||
|   }; | ||||
|   return &handler; | ||||
| } | ||||
									
										
											File diff suppressed because it is too large
											Load Diff
										
									
								
							
						| @ -1,73 +0,0 @@ | ||||
| /* SoX Memory allocation functions
 | ||||
|  * | ||||
|  * Copyright (c) 2005-2006 Reuben Thomas.  All rights reserved. | ||||
|  * | ||||
|  * This library is free software; you can redistribute it and/or modify it | ||||
|  * under the terms of the GNU Lesser General Public License as published by | ||||
|  * the Free Software Foundation; either version 2.1 of the License, or (at | ||||
|  * your option) any later version. | ||||
|  * | ||||
|  * This library is distributed in the hope that it will be useful, but | ||||
|  * WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser | ||||
|  * General Public License for more details. | ||||
|  * | ||||
|  * You should have received a copy of the GNU Lesser General Public License | ||||
|  * along with this library; if not, write to the Free Software Foundation, | ||||
|  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA | ||||
|  */ | ||||
| 
 | ||||
| #include "sox_i.h" | ||||
| #include <stdlib.h> | ||||
| 
 | ||||
| static void *lsx_checkptr(void *ptr) | ||||
| { | ||||
|   if (!ptr) { | ||||
|     lsx_fail("out of memory"); | ||||
|     exit(2); | ||||
|   } | ||||
| 
 | ||||
|   return ptr; | ||||
| } | ||||
| 
 | ||||
| /* Resize an allocated memory area; abort if not possible.
 | ||||
|  * | ||||
|  * For malloc, `If the size of the space requested is zero, the behavior is | ||||
|  * implementation defined: either a null pointer is returned, or the | ||||
|  * behavior is as if the size were some nonzero value, except that the | ||||
|  * returned pointer shall not be used to access an object' | ||||
|  */ | ||||
| void *lsx_realloc(void *ptr, size_t newsize) | ||||
| { | ||||
|   if (ptr && newsize == 0) { | ||||
|     free(ptr); | ||||
|     return NULL; | ||||
|   } | ||||
| 
 | ||||
|   return lsx_checkptr(realloc(ptr, newsize)); | ||||
| } | ||||
| 
 | ||||
| void *lsx_malloc(size_t size) | ||||
| { | ||||
|   return lsx_checkptr(malloc(size + !size)); | ||||
| } | ||||
| 
 | ||||
| void *lsx_calloc(size_t n, size_t size) | ||||
| { | ||||
|   return lsx_checkptr(calloc(n + !n, size + !size)); | ||||
| } | ||||
| 
 | ||||
| void *lsx_realloc_array(void *p, size_t n, size_t size) | ||||
| { | ||||
|   if (n > (size_t)-1 / size) { | ||||
|     lsx_fail("malloc size overflow"); | ||||
|     exit(2); | ||||
|   } | ||||
| 
 | ||||
|   return lsx_realloc(p, n * size); | ||||
| } | ||||
| 
 | ||||
| char *lsx_strdup(const char *s) | ||||
| { | ||||
|   return lsx_checkptr(strdup(s)); | ||||
| } | ||||
| @ -1,36 +0,0 @@ | ||||
| /* libSoX Memory allocation functions
 | ||||
|  * | ||||
|  * Copyright (c) 2005-2006 Reuben Thomas.  All rights reserved. | ||||
|  * | ||||
|  * This library is free software; you can redistribute it and/or modify it | ||||
|  * under the terms of the GNU Lesser General Public License as published by | ||||
|  * the Free Software Foundation; either version 2.1 of the License, or (at | ||||
|  * your option) any later version. | ||||
|  * | ||||
|  * This library is distributed in the hope that it will be useful, but | ||||
|  * WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser | ||||
|  * General Public License for more details. | ||||
|  * | ||||
|  * You should have received a copy of the GNU Lesser General Public License | ||||
|  * along with this library; if not, write to the Free Software Foundation, | ||||
|  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA | ||||
|  */ | ||||
| 
 | ||||
| #ifndef LSX_MALLOC_H | ||||
| #define LSX_MALLOC_H | ||||
| 
 | ||||
| #include <stddef.h> | ||||
| #include <string.h> | ||||
| 
 | ||||
| LSX_RETURN_VALID void *lsx_malloc(size_t size); | ||||
| LSX_RETURN_VALID void *lsx_calloc(size_t n, size_t size); | ||||
| LSX_RETURN_VALID void *lsx_realloc_array(void *p, size_t n, size_t size); | ||||
| LSX_RETURN_VALID char *lsx_strdup(const char *s); | ||||
| 
 | ||||
| #define lsx_Calloc(v,n)  v = lsx_calloc(n,sizeof(*(v))) | ||||
| #define lsx_memdup(p,s) ((p)? memcpy(lsx_malloc(s), p, s) : NULL) | ||||
| #define lsx_valloc(v,n)  v = lsx_realloc_array(NULL, n, sizeof(*(v))) | ||||
| #define lsx_revalloc(v,n)  v = lsx_realloc_array(v, n, sizeof(*(v))) | ||||
| 
 | ||||
| #endif | ||||
					Loading…
					
					
				
		Reference in new issue