ref: 8a4f90fa0ac35ff2e742c904b2572ed4475e58ae
parent: 8c54fac1999ec9ebb429cf0e0f3c40de2b9127d6
author: cbagwell <cbagwell>
date: Sat Dec 4 17:13:16 EST 1999
Major library support updates. Stereo GSM support.
--- a/TODO
+++ b/TODO
@@ -6,11 +6,9 @@
you can grab the source code from the .au handler and software
is avaliable from public sources for the rest.
- o Add GSM support to WAV format. Goes with the above but used
- most often.
-
o highpass and lowpass filters don't let you specify the cut
of freq. Need some improvements to these filters.
+ SJB: The old highp.c filter is IMHO broken, need to review that code.
o Create a version of OSS and Sun driver that can play and record from the
same device in duplex.
@@ -18,6 +16,8 @@
o Internally sox can handle multiple effects on a given sound file.
Add support for this from the command line.
+ o Add support for mixing multiple inputs from command line.
+
o Endian checks are probably invalid on 64-bit machines. Need to use
something a more constant size the "int". Probably should make it
at least a util function/macro that can be overriden at compile time.
@@ -30,7 +30,7 @@
the urge to come up with their own file format.
o More effects! I don't know DSP at all. A Pitch Shifter is high
- on the list.
+ on the list. Spectrum analyser, etc, using FFTW lib.
o Loop support for all formats that know about it. WAV has
some support for loops ("cue-points") but no support for
--- a/libst.c
+++ b/libst.c
@@ -35,7 +35,7 @@
st_linear_to_ulaw( sample )
short sample;
{
- static const int exp_lut[256] =
+ static const unsigned char exp_lut[256] =
{0,0,1,1,2,2,2,2,3,3,3,3,3,3,3,3,
4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,
@@ -107,7 +107,7 @@
#else
-unsigned char ulaw_comp_table[16384] = {
+const unsigned char ulaw_comp_table[16384] = {
0xff,0xfe,0xfe,0xfd,0xfd,0xfc,0xfc,0xfb,
0xfb,0xfa,0xfa,0xf9,0xf9,0xf8,0xf8,0xf7,
0xf7,0xf6,0xf6,0xf5,0xf5,0xf4,0xf4,0xf3,
@@ -2157,7 +2157,7 @@
0x77,0x77,0x78,0x78,0x79,0x79,0x7a,0x7a,
0x7b,0x7b,0x7c,0x7c,0x7d,0x7d,0x7e,0x7e};
-int ulaw_exp_table[256] = {
+const short ulaw_exp_table[256] = {
-32124,-31100,-30076,-29052,-28028,-27004,-25980,-24956,
-23932,-22908,-21884,-20860,-19836,-18812,-17788,-16764,
-15996,-15484,-14972,-14460,-13948,-13436,-12924,-12412,
@@ -2211,7 +2211,8 @@
st_linear_to_Alaw( sample )
short sample;
{
- static int exp_lut[128] = {1,1,2,2,3,3,3,3,
+ static const unsigned char exp_lut[128] =
+ {1,1,2,2,3,3,3,3,
4,4,4,4,4,4,4,4,
5,5,5,5,5,5,5,5,
5,5,5,5,5,5,5,5,
@@ -2275,7 +2276,7 @@
#else
-unsigned char Alaw_comp_table[16384] = {
+unsigned const char Alaw_comp_table[16384] = {
0xD5,0xD5,0xD5,0xD5,0xD4,0xD4,0xD4,0xD4,
0xD7,0xD7,0xD7,0xD7,0xD6,0xD6,0xD6,0xD6,
0xD1,0xD1,0xD1,0xD1,0xD0,0xD0,0xD0,0xD0,
@@ -4325,7 +4326,7 @@
0x51,0x56,0x56,0x56,0x56,0x57,0x57,0x57,
0x57,0x54,0x54,0x54,0x54,0x55,0x55,0x55};
-int Alaw_exp_table[256] = {
+const short Alaw_exp_table[256] = {
-5504, -5248, -6016, -5760, -4480, -4224, -4992, -4736,
-7552, -7296, -8064, -7808, -6528, -6272, -7040, -6784,
-2752, -2624, -3008, -2880, -2240, -2112, -2496, -2368,
--- a/libst.h
+++ b/libst.h
@@ -20,43 +20,21 @@
/******************************************************************/
#ifdef FAST_ULAW_CONVERSION
extern int ulaw_exp_table[256];
-extern unsigned char ulaw_comp_table[16384];
+extern const unsigned char ulaw_comp_table[16384];
#define st_ulaw_to_linear(ulawbyte) ulaw_exp_table[ulawbyte]
#define st_linear_to_ulaw(linearword) ulaw_comp_table[((short)linearword / 4) & 0x3fff]
#else
-unsigned char st_linear_to_ulaw( /* short sample */ );
-int st_ulaw_to_linear( /* unsigned char ulawbyte */ );
+unsigned char st_linear_to_ulaw(P1(short));
+int st_ulaw_to_linear(P1(unsigned char));
#endif
#ifdef FAST_ALAW_CONVERSION
-extern int Alaw_exp_table[256];
-extern unsigned char Alaw_comp_table[16384];
+extern const short Alaw_exp_table[256];
+extern const unsigned char Alaw_comp_table[16384];
#define st_Alaw_to_linear(Alawbyte) Alaw_exp_table[Alawbyte]
#define st_linear_to_Alaw(linearword) Alaw_comp_table[((short)linearword / 4) & 0x3fff]
#else
-unsigned char st_linear_to_Alaw( /* short sample */ );
-int st_Alaw_to_linear( /* unsigned char ulawbyte */ );
+unsigned char st_linear_to_Alaw(P1(short));
+int st_Alaw_to_linear(P1(unsigned char));
#endif
-/* Greatest Common Demoninator */
-LONG st_gcd(/* a, b */);
-/* Least Common Multiple */
-LONG st_lcm(/* a, b */);
-
-/****************************************************/
-/* Prototypes for internal cross-platform functions */
-/****************************************************/
-
-#ifndef HAVE_RAND
-extern int rand();
-extern void srand(/* seed */);
-#endif
-extern void st_initrand();
-
-extern LONG st_clip24();
-extern void st_sine();
-extern void st_triangle();
-
-#ifndef HAVE_STRERROR
-char *strerror(/*errorcode*/);
-#endif
--- a/pick.c
+++ b/pick.c
@@ -16,7 +16,6 @@
*/
#include "st.h"
-#include "libst.h"
/* Private data for SKEL file */
typedef struct pickstuff {
--- a/src/8svx.c
+++ b/src/8svx.c
@@ -12,20 +12,16 @@
#include <unistd.h> /* For SEEK_* defines if not found in stdio */
#endif
-#ifdef HAVE_MALLOC_H
-#include <malloc.h>
-#endif
-
#include "st.h"
/* Private data used by writer */
struct svxpriv {
- ULONG nsamples;
+ ULONG nsamples;
FILE *ch[4];
};
-void svxwriteheader(P2(ft_t, LONG));
-
+static void svxwriteheader(P2(ft_t, LONG));
+
/*======================================================================*/
/* 8SVXSTARTREAD */
/*======================================================================*/
@@ -307,7 +303,7 @@
/* 8SVXWRITEHEADER */
/*======================================================================*/
#define SVXHEADERSIZE 100
-void svxwriteheader(ft,nsamples)
+static void svxwriteheader(ft,nsamples)
ft_t ft;
LONG nsamples;
{
--- a/src/adpcm.c
+++ b/src/adpcm.c
@@ -51,7 +51,8 @@
/* these are step-size adjust factors, where
* 1.0 is scaled to 0x100
*/
-static LONG stepAdjustTable[] = {
+static const
+LONG stepAdjustTable[] = {
230, 230, 230, 230, 307, 409, 512, 614,
768, 614, 512, 409, 307, 230, 230, 230
};
@@ -60,7 +61,7 @@
appear in the actual WAVE file. They should be read in
in case a sound program added extras to the list. */
-short iCoef[7][2] = {
+const short iCoef[7][2] = {
{ 256, 0},
{ 512,-256},
{ 0, 0},
--- a/src/adpcm.h
+++ b/src/adpcm.h
@@ -8,12 +8,15 @@
#define LONG long
#endif
/* FIXME: This breaks on Alphas! */
+/* SJB: Not really, because when used with sox, LONG and ULONG are
+ * already defined before adpcm.h is included
+ */
#ifndef ULONG
-#define ULONG u_long
+#define ULONG unsigned long
#endif
/* default coef sets */
-extern short iCoef[7][2];
+extern const short iCoef[7][2];
/* AdpcmBlockExpandI() outputs interleaved samples into one output buffer */
extern const char *AdpcmBlockExpandI(
--- a/src/aiff.c
+++ b/src/aiff.c
@@ -33,6 +33,8 @@
* for endianness was being performed AFTER reading the header instead
* of before reading it.
*
+ * Nov 25, 1999 - internal functions made static
+ *
*/
#include <math.h>
@@ -44,10 +46,6 @@
#include <unistd.h> /* For SEEK_* defines if not found in stdio */
#endif
-#ifdef HAVE_MALLOC_H
-#include <malloc.h>
-#endif
-
#include "st.h"
/* Private data used by writer */
@@ -55,13 +53,14 @@
ULONG nsamples; /* number of 1-channel samples read or written */
};
-double read_ieee_extended();
-void aiffwriteheader(P2(ft_t, LONG));
-void write_ieee_extended(P2(ft_t, double));
-double ConvertFromIeeeExtended();
-void ConvertToIeeeExtended(P2(double, char *));
-void textChunk(P3(char **text, char *chunkDescription, ft_t ft));
-void reportInstrument(P1(ft_t ft));
+/* forward declarations */
+static double read_ieee_extended(P1(ft_t));
+static void aiffwriteheader(P2(ft_t, LONG));
+static void write_ieee_extended(P2(ft_t, double));
+static double ConvertFromIeeeExtended(P1(unsigned char*));
+static void ConvertToIeeeExtended(P2(double, char *));
+static void textChunk(P3(char **text, char *chunkDescription, ft_t ft));
+static void reportInstrument(P1(ft_t ft));
void aiffstartread(ft)
ft_t ft;
@@ -366,7 +365,7 @@
}
/* print out the MIDI key allocations, loop points, directions etc */
-void reportInstrument(ft)
+static void reportInstrument(ft)
ft_t ft;
{
int loopNum;
@@ -393,7 +392,7 @@
}
/* Process a text chunk, allocate memory, display it if verbose and return */
-void textChunk(text, chunkDescription, ft)
+static void textChunk(text, chunkDescription, ft)
char **text;
char *chunkDescription;
ft_t ft;
@@ -532,7 +531,7 @@
aiffwriteheader(ft, p->nsamples / ft->info.channels);
}
-void aiffwriteheader(ft, nframes)
+static void aiffwriteheader(ft, nframes)
ft_t ft;
LONG nframes;
{
@@ -635,7 +634,7 @@
wlong(ft, (LONG) 0); /* block size */
}
-double read_ieee_extended(ft)
+static double read_ieee_extended(ft)
ft_t ft;
{
char buf[10];
@@ -644,7 +643,7 @@
return ConvertFromIeeeExtended(buf);
}
-void write_ieee_extended(ft, x)
+static void write_ieee_extended(ft, x)
ft_t ft;
double x;
{
@@ -701,7 +700,7 @@
# define FloatToUnsigned(f) ((ULONG)(((LONG)(f - 2147483648.0)) + 2147483647L) + 1)
-void ConvertToIeeeExtended(num, bytes)
+static void ConvertToIeeeExtended(num, bytes)
double num;
char *bytes;
{
@@ -800,7 +799,7 @@
* Extended precision IEEE floating-point conversion routine.
****************************************************************/
-double ConvertFromIeeeExtended(bytes)
+static double ConvertFromIeeeExtended(bytes)
unsigned char *bytes; /* LCN */
{
double f;
--- a/src/alsa.c
+++ b/src/alsa.c
@@ -13,9 +13,6 @@
* based on info grabed from aplay.c in alsa-utils package.
*/
-#ifdef HAVE_MALLOC_H
-#include <malloc.h>
-#endif
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
@@ -24,22 +21,7 @@
#include <linux/asound.h>
#include <sys/ioctl.h>
#include "st.h"
-#include "libst.h"
-char *get_style(style)
-int style;
-{
- switch(style)
- {
- case UNSIGNED: return "UNSIGNED";
- case SIGN2: return "SIGNED LINEAR 2's Comp";
- case ULAW: return "uLaw";
- case ALAW: return "aLaw";
- case ADPCM: return "ADPCM";
- default: return "unknown";
- }
-}
-
/*
* Do anything required before you start reading samples.
* Read file header.
@@ -94,7 +76,7 @@
fmt = SND_PCM_SFMT_U8;
break;
default:
- fail("Hardware does not support %s output", get_style(ft->info.style));
+ fail("Hardware does not support %s output", styles[ft->info.style]);
break;
}
}
@@ -112,7 +94,7 @@
fmt = SND_PCM_SFMT_U16_LE;
break;
default:
- fail("Hardware does not support %s output", get_style(ft->info.style));
+ fail("Hardware does not support %s output", styles[ft->info.style]);
break;
}
}
@@ -186,7 +168,7 @@
fmt = SND_PCM_SFMT_U8;
break;
default:
- fail("Hardware does not support %s output", get_style(ft->info.style));
+ fail("Hardware does not support %s output", styles[ft->info.style]);
break;
}
}
@@ -204,7 +186,7 @@
fmt = SND_PCM_SFMT_U16_LE;
break;
default:
- fail("Hardware does not support %s output", get_style(ft->info.style));
+ fail("Hardware does not support %s output", styles[ft->info.style]);
break;
}
}
--- a/src/au.c
+++ b/src/au.c
@@ -22,9 +22,6 @@
#include "st.h"
#include "g72x.h"
#include <stdlib.h>
-#ifdef HAVE_MALLOC_H
-#include <malloc.h>
-#endif
/* Magic numbers used in Sun and NeXT audio files */
#define SUN_MAGIC 0x2e736e64 /* Really '.snd' */
@@ -58,7 +55,7 @@
int in_bits;
};
-void auwriteheader(P2(ft_t ft, ULONG data_size));
+static void auwriteheader(P2(ft_t ft, ULONG data_size));
void austartread(ft)
ft_t ft;
@@ -243,7 +240,7 @@
* Returns 1 if there is residual input, returns -1 if eof, else returns 0.
* (Adapted from Sun's decode.c.)
*/
-int
+static int
unpack_input(ft, code)
ft_t ft;
unsigned char *code;
@@ -311,7 +308,7 @@
auwriteheader(ft, p->data_size);
}
-void auwriteheader(ft, data_size)
+static void auwriteheader(ft, data_size)
ft_t ft;
ULONG data_size;
{
--- a/src/auto.c
+++ b/src/auto.c
@@ -17,8 +17,6 @@
#include "st.h"
#include <string.h>
-void gettype();
-
void autostartread(ft)
ft_t ft;
{
--- a/src/chorus.c
+++ b/src/chorus.c
@@ -63,13 +63,9 @@
*/
#include <stdlib.h> /* Harmless, and prototypes atof() etc. --dgc */
-#ifdef HAVE_MALLOC_H
-#include <malloc.h>
-#endif
#include <math.h>
#include <string.h>
#include "st.h"
-#include "libst.h"
#define MOD_SINE 0
#define MOD_TRIANGLE 1
@@ -175,10 +171,12 @@
sizeof(int) * chorus->length[i]);
if ( chorus->modulation[i] == MOD_SINE )
st_sine(chorus->lookup_tab[i], chorus->length[i],
- chorus->samples[i] - 1, chorus->depth_samples[i]);
+ chorus->depth_samples[i] - 1,
+ chorus->depth_samples[i]);
else
st_triangle(chorus->lookup_tab[i], chorus->length[i],
- chorus->samples[i] - 1, chorus->depth_samples[i]);
+ chorus->samples[i] - 1,
+ chorus->depth_samples[i]);
chorus->phase[i] = 0;
if ( chorus->samples[i] > chorus->maxsamples )
--- a/src/cvsd.c
+++ b/src/cvsd.c
@@ -47,7 +47,6 @@
#include "cvsdfilt.h"
#include "st.h"
-#include "libst.h"
/* ---------------------------------------------------------------------- */
@@ -97,7 +96,7 @@
/* ---------------------------------------------------------------------- */
-float float_conv(fp1, fp2, n)
+static float float_conv(fp1, fp2, n)
float *fp1;
float *fp2;
int n;
@@ -428,7 +427,7 @@
#define DVMS_HEADER_LEN 120
/* ---------------------------------------------------------------------- */
-
+/* SJB: should these be in misc.c instead? */
static ULONG get32(p)
unsigned char **p;
{
--- a/src/dat.c
+++ b/src/dat.c
@@ -21,7 +21,6 @@
*/
#include "st.h"
-#include "libst.h"
/* Private data for dat file */
typedef struct dat {
@@ -28,12 +27,13 @@
double timevalue, deltat;
} *dat_t;
-LONG roundoff(x)
+/* SJB: should this be moved to misc.c ? */
+static LONG roundoff(x)
double x;
{
if (x < 0.0) return(x - 0.5);
else return(x + 0.5);
- }
+}
void
datstartread(ft)
--- a/src/echo.c
+++ b/src/echo.c
@@ -56,12 +56,8 @@
*/
#include <stdlib.h> /* Harmless, and prototypes atof() etc. --dgc */
-#ifdef HAVE_MALLOC_H
-#include <malloc.h>
-#endif
#include <math.h>
#include "st.h"
-#include "libst.h"
#define DELAY_BUFSIZ ( 50L * MAXRATE )
#define MAX_ECHOS 7 /* 24 bit x ( 1 + MAX_ECHOS ) = */
--- a/src/echos.c
+++ b/src/echos.c
@@ -47,12 +47,8 @@
*/
#include <stdlib.h> /* Harmless, and prototypes atof() etc. --dgc */
-#ifdef HAVE_MALLOC_H
-#include <malloc.h>
-#endif
#include <math.h>
#include "st.h"
-#include "libst.h"
#define DELAY_BUFSIZ ( 50L * MAXRATE )
#define MAX_ECHOS 7 /* 24 bit x ( 1 + MAX_ECHOS ) = */
--- a/src/filter.c
+++ b/src/filter.c
@@ -39,9 +39,6 @@
#include <math.h>
#include <string.h>
#include <stdlib.h>
-#ifdef HAVE_MALLOC_H
-#include <malloc.h>
-#endif
#include "st.h"
@@ -69,6 +66,7 @@
Float *X, *Y; /* I/O buffers */
} *filter_t;
+/* makeFilter() declared in resample.c */
extern int
makeFilter(P5(Float Fp[], LONG Nwing, double Froll, double Beta, LONG Num));
--- a/src/flanger.c
+++ b/src/flanger.c
@@ -53,9 +53,6 @@
*/
#include <stdlib.h> /* Harmless, and prototypes atof() etc. --dgc */
-#ifdef HAVE_MALLOC_H
-#include <malloc.h>
-#endif
#include <math.h>
#include <string.h>
#include "st.h"
@@ -157,9 +154,11 @@
if ( flanger->modulation == MOD_SINE )
st_sine(flanger->lookup_tab, flanger->length,
+ flanger->maxsamples - 1,
flanger->maxsamples - 1);
else
st_triangle(flanger->lookup_tab, flanger->length,
+ (flanger->maxsamples - 1) * 2,
flanger->maxsamples - 1);
flanger->counter = 0;
flanger->phase = 0;
--- a/src/gsm.c
+++ b/src/gsm.c
@@ -22,24 +22,39 @@
* July 19, 1998 - Chris Bagwell (cbagwell@sprynet.com)
* Added GSM support to SOX from patches floating around with the help
* of Dima Barsky (ess2db@ee.surrey.ac.uk).
+ *
+ * Nov. 26, 1999 - Stan Brooks (stabro@megsinet.com)
+ * Rewritten to support multiple channels
*/
#include "st.h"
#include "gsm.h"
+#define MAXCHANS 16
+
+/* sizeof(gsm_frame) */
+#define FRAMESIZE 33
+/* samples per gsm_frame */
+#define BLOCKSIZE 160
+
/* Private data */
struct gsmpriv {
- gsm handle;
- gsm_signal sample[160];
- int index;
+ int channels;
+ gsm_signal *samples;
+ gsm_signal *samplePtr;
+ gsm_signal *sampleTop;
+ gsm_byte *frames;
+ gsm handle[MAXCHANS];
};
-void
-gsmstartread(ft)
+static void
+gsmstart_rw(ft,w)
ft_t ft;
+int w; /* w != 0 is write */
{
struct gsmpriv *p = (struct gsmpriv *) ft->priv;
-
+ int ch;
+
/* Sanity check */
if (sizeof(struct gsmpriv) > PRIVSIZE)
fail(
@@ -50,26 +65,32 @@
ft->info.size = BYTE;
if (!ft->info.rate)
ft->info.rate = 8000;
- p->handle = gsm_create();
- if (!p->handle)
- fail("unable to create GSM stream");
- p->index = 0;
+
+ p->channels = ft->info.channels;
+ if (p->channels > MAXCHANS || p->channels <= 0)
+ fail("gsm: channels(%d) must be in 1-16", ft->info.channels);
+
+ for (ch=0; ch<p->channels; ch++) {
+ p->handle[ch] = gsm_create();
+ if (!p->handle[ch])
+ fail("unable to create GSM stream");
+ }
+ p->frames = (gsm_byte*) malloc(p->channels*FRAMESIZE);
+ p->samples = (gsm_signal*) malloc(BLOCKSIZE * (p->channels+1) * sizeof(gsm_signal));
+ p->sampleTop = p->samples + BLOCKSIZE*p->channels;
+ p->samplePtr = (w)? p->samples : p->sampleTop;
}
-void
-gsmstartwrite(ft)
+void gsmstartread(ft)
ft_t ft;
{
- struct gsmpriv *p = (struct gsmpriv *) ft->priv;
+ gsmstart_rw(ft,0);
+}
- ft->info.style = GSM;
- ft->info.size = BYTE;
- if (!ft->info.rate)
- ft->info.rate = 8000;
- p->handle = gsm_create();
- if (!p->handle)
- fail("unable to create GSM stream");
- p->index = 0;
+void gsmstartwrite(ft)
+ft_t ft;
+{
+ gsmstart_rw(ft,1);
}
/*
@@ -79,55 +100,94 @@
* Return number of samples read.
*/
-LONG
-gsmread(ft, buf, samp)
+LONG gsmread(ft, buf, samp)
ft_t ft;
long *buf, samp;
{
- int bytes;
int done = 0;
- gsm_frame frame;
+ int r, ch, chans;
+ gsm_signal *gbuff;
struct gsmpriv *p = (struct gsmpriv *) ft->priv;
- while (p->index && (p->index < 160) && (done < samp))
- buf[done++] = LEFT(p->sample[p->index++], 16);
+ chans = p->channels;
while (done < samp)
{
- p->index = 0;
- bytes = fread( frame, 1, sizeof(frame), ft->fp );
- if (bytes <= 0)
- return done;
- if (bytes < sizeof(frame))
- fail("invalid frame size: %d bytes", bytes);
- if (gsm_decode(p->handle, frame, p->sample) < 0)
- fail("error during GSM decode");
- while ((p->index < 160) && (done < samp))
- buf[done++] = LEFT(p->sample[p->index++], 16);
+ while (p->samplePtr < p->sampleTop && done < samp)
+ buf[done++] = LEFT(*(p->samplePtr)++, 16);
+
+ if (done>=samp) break;
+
+ r = fread(p->frames, p->channels*FRAMESIZE, 1, ft->fp);
+ if (r != 1) break;
+
+ p->samplePtr = p->samples;
+ for (ch=0; ch<chans; ch++) {
+ int i;
+ gsm_signal *gsp;
+
+ gbuff = p->sampleTop;
+ if (gsm_decode(p->handle[ch], p->frames + ch*FRAMESIZE, gbuff) < 0)
+ fail("error during GSM decode");
+
+ gsp = p->samples + ch;
+ for (i=0; i<BLOCKSIZE; i++) {
+ *gsp = *gbuff++;
+ gsp += chans;
+ }
+ }
}
return done;
}
-int
-gsmwrite(ft, buf, samp)
+static void gsmflush(ft)
ft_t ft;
+{
+ int r, ch, chans;
+ gsm_signal *gbuff;
+ struct gsmpriv *p = (struct gsmpriv *) ft->priv;
+
+ chans = p->channels;
+
+ /* zero-fill samples as needed */
+ while (p->samplePtr < p->sampleTop)
+ *(p->samplePtr)++ = 0;
+
+ gbuff = p->sampleTop;
+ for (ch=0; ch<chans; ch++) {
+ int i;
+ gsm_signal *gsp;
+
+ gsp = p->samples + ch;
+ for (i=0; i<BLOCKSIZE; i++) {
+ gbuff[i] = *gsp;
+ gsp += chans;
+ }
+ gsm_encode(p->handle[ch], gbuff, p->frames);
+ r = fwrite(p->frames, FRAMESIZE, 1, ft->fp);
+ if (r != 1)
+ fail("write error");
+ }
+ p->samplePtr = p->samples;
+
+ return;
+}
+
+int gsmwrite(ft, buf, samp)
+ft_t ft;
long *buf, samp;
{
int done = 0;
- gsm_frame frame;
struct gsmpriv *p = (struct gsmpriv *) ft->priv;
while (done < samp)
{
- while ((p->index < 160) && (done < samp))
- p->sample[p->index++] = RIGHT(buf[done++], 16);
- if (p->index < 160)
- return done;
- gsm_encode(p->handle, p->sample, frame);
- if (fwrite(frame, 1, sizeof(frame), ft->fp) != sizeof(frame))
- fail("write error");
- p->index = 0;
+ while ((p->samplePtr < p->sampleTop) && (done < samp))
+ *(p->samplePtr)++ = RIGHT(buf[done++], 16);
+
+ if (p->samplePtr == p->sampleTop)
+ gsmflush(ft);
}
return done;
@@ -138,8 +198,13 @@
ft_t ft;
{
struct gsmpriv *p = (struct gsmpriv *) ft->priv;
+ int ch;
- gsm_destroy(p->handle);
+ for (ch=0; ch<p->channels; ch++)
+ gsm_destroy(p->handle[ch]);
+
+ free(p->samples);
+ free(p->frames);
}
void
@@ -146,17 +211,11 @@
gsmstopwrite(ft)
ft_t ft;
{
- gsm_frame frame;
struct gsmpriv *p = (struct gsmpriv *) ft->priv;
- if (p->index)
- {
- while (p->index < 160)
- p->sample[p->index++] = 0;
- gsm_encode(p->handle, p->sample, frame);
- if (fwrite(frame, 1, sizeof(frame), ft->fp) != sizeof(frame))
- fail("write error");
- }
- gsm_destroy(p->handle);
+ if (p->samplePtr > p->samples)
+ gsmflush(ft);
+
+ gsmstopread(ft); /* destroy handles and free buffers */
}
#endif /* HAVE_LIBGSM */
--- a/src/hcom.c
+++ b/src/hcom.c
@@ -24,9 +24,6 @@
#include "st.h"
#include <string.h>
#include <stdlib.h>
-#ifdef HAVE_MALLOC_H
-#include <malloc.h>
-#endif
/* Dictionary entry for Huffman (de)compression */
typedef struct {
@@ -50,7 +47,7 @@
short sample;
};
-void skipbytes(P2(ft_t, int));
+static void skipbytes(P2(ft_t, int));
void hcomstartread(ft)
ft_t ft;
@@ -141,7 +138,7 @@
p->nrbits = -1; /* Special case to get first byte */
}
-void skipbytes(ft, n)
+static void skipbytes(ft, n)
ft_t ft;
int n;
{
@@ -301,6 +298,8 @@
passed around in a structure instead. Use static so we don't
polute global name space. */
+/* SJB: FIXME: dangerous static variables, need to analyse code */
+
static dictent dictionary[511];
static dictent *de;
static LONG codes[256];
@@ -307,7 +306,7 @@
static LONG codesize[256];
static LONG checksum;
-void makecodes(e, c, s, b)
+static void makecodes(e, c, s, b)
int e, c, s, b;
{
if(dictionary[e].dict_leftson < 0) {
@@ -322,7 +321,8 @@
static LONG curword;
static int nbits;
-void putlong(c, v)
+/* SJB: candidates for misc.c */
+static void putlong(c, v)
unsigned char *c;
LONG v;
{
@@ -332,7 +332,7 @@
*c++ = v & 0xff;
}
-void putshort(c, v)
+static void putshort(c, v)
unsigned char *c;
short v;
{
@@ -341,7 +341,7 @@
}
-void putcode(c, df)
+static void putcode(c, df)
unsigned char c;
unsigned char ** df;
{
@@ -364,7 +364,7 @@
}
}
-void compress(df, dl, fr)
+static void compress(df, dl, fr)
unsigned char **df;
LONG *dl;
float fr;
@@ -472,7 +472,7 @@
*dl = l; /* and its compressed length */
}
-void padbytes(ft, n)
+static void padbytes(ft, n)
ft_t ft;
int n;
{
--- a/src/highp.c
+++ b/src/highp.c
@@ -19,6 +19,7 @@
* A = 2.0 * pi * center
* B = exp(-A / frequency)
*/
+/* SJB: Note: highp filter is currently broken, see test gnuplot graphs */
#include <math.h>
#include "st.h"
--- a/src/ima_rw.h
+++ b/src/ima_rw.h
@@ -22,6 +22,9 @@
# define SAMPL short
#endif
/* FIXME: This breaks on Alphas! */
+/* SJB: Not really, because when used with sox, LONG and ULONG are
+ * already defined before adpcm.h is included
+ */
#ifndef ULONG
# define ULONG unsigned long
#endif
--- a/src/mask.c
+++ b/src/mask.c
@@ -15,7 +15,6 @@
#include <stdlib.h>
#include <math.h>
#include "st.h"
-#include "libst.h"
#define HALFABIT 1.44 /* square root of 2 */
--- a/src/maud.c
+++ b/src/maud.c
@@ -18,7 +18,6 @@
*/
#include "st.h"
-#include "libst.h"
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
@@ -32,7 +31,7 @@
ULONG nsamples;
};
-void maudwriteheader(P1(ft_t));
+static void maudwriteheader(P1(ft_t));
/*
* Do anything required before you start reading samples.
@@ -263,7 +262,7 @@
}
#define MAUDHEADERSIZE (4+(4+4+32)+(4+4+32)+(4+4))
-void maudwriteheader(ft)
+static void maudwriteheader(ft)
ft_t ft;
{
struct maudstuff * p = (struct maudstuff *) ft->priv;
--- a/src/misc.c
+++ b/src/misc.c
@@ -11,16 +11,15 @@
* Sound Tools miscellaneous stuff.
*/
-#include <stdio.h>
-#include <stdlib.h>
-#include <time.h>
-#include <math.h>
#include "st.h"
-#include "libst.h"
#include "version.h"
#include "patchlvl.h"
+#include <math.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <time.h>
-char *sizes[] = {
+const char *sizes[] = {
"NONSENSE!",
"bytes",
"shorts",
@@ -31,7 +30,7 @@
"IEEE floats"
};
-char *styles[] = {
+const char *styles[] = {
"NONSENSE!",
"unsigned",
"signed (2's complement)",
@@ -42,8 +41,8 @@
"gsm",
};
-char readerr[] = "Premature EOF while reading sample file.";
-char writerr[] = "Error writing sample file. You are probably out of disk space.";
+static const char readerr[] = "Premature EOF while reading sample file.";
+static const char writerr[] = "Error writing sample file. You are probably out of disk space.";
/* Utilities */
@@ -208,8 +207,8 @@
/* dummy routines for do-nothing functions */
-void nothing() {}
-LONG nothing_success() {return(0);}
+void nothing(P0) {}
+LONG nothing_success(P0) {return(0);}
/* dummy drain routine for effects */
void null_drain(effp, obuf, osamp)
@@ -258,7 +257,7 @@
#endif
/* Util to set initial seed so that we are a little less non-random */
-void st_initrand() {
+void st_initrand(P0) {
time_t t;
time(&t);
@@ -278,14 +277,17 @@
/* This was very painful. We need a sine library. */
-void st_sine(buf, len, depth)
+void st_sine(buf, len, max, depth)
int *buf;
-long len;
-long depth;
+LONG len;
+int max;
+int depth;
{
long i;
+ int offset;
double val;
+ offset = max - depth;
for (i = 0; i < len; i++) {
val = sin((double)i/(double)len * 2.0 * M_PI);
buf[i] = (int) ((1.0 + val) * depth / 2.0);
@@ -292,25 +294,28 @@
}
}
-void st_triangle(buf, len, depth)
+void st_triangle(buf, len, max, depth)
int *buf;
-long len;
-long depth;
+LONG len;
+int max;
+int depth;
{
- long i;
+ LONG i;
+ int offset;
double val;
+ offset = max - 2 * depth;
for (i = 0; i < len / 2; i++) {
val = i * 2.0 / len;
- buf[i] = (int) (val * depth);
+ buf[i] = offset + (int) (val * 2.0 * (double)depth);
}
for (i = len / 2; i < len ; i++) {
val = (len - i) * 2.0 / len;
- buf[i] = (int) (val * depth);
+ buf[i] = offset + (int) (val * 2.0 * (double)depth);
}
}
-char *
+const char *
version()
{
static char versionstr[20];
--- a/src/oss.c
+++ b/src/oss.c
@@ -35,7 +35,6 @@
#endif
#include <sys/ioctl.h>
#include "st.h"
-#include "libst.h"
/*
* Do anything required before you start reading samples.
--- a/src/phaser.c
+++ b/src/phaser.c
@@ -56,9 +56,6 @@
*/
#include <stdlib.h> /* Harmless, and prototypes atof() etc. --dgc */
-#ifdef HAVE_MALLOC_H
-#include <malloc.h>
-#endif
#include <math.h>
#include <string.h>
#include "st.h"
@@ -154,9 +151,11 @@
if ( phaser->modulation == MOD_SINE )
st_sine(phaser->lookup_tab, phaser->length,
+ phaser->maxsamples - 1,
phaser->maxsamples - 1);
else
st_triangle(phaser->lookup_tab, phaser->length,
+ (phaser->maxsamples - 1) * 2,
phaser->maxsamples - 1);
phaser->counter = 0;
phaser->phase = 0;
--- a/src/polyphas.c
+++ b/src/polyphas.c
@@ -31,11 +31,7 @@
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
-#ifdef HAVE_MALLOC_H
-#include <malloc.h>
-#endif
#include "st.h"
-#include "libst.h"
#define Float float/*double*/
#define ISCALE 0x10000
@@ -345,7 +341,7 @@
buffer must already be allocated.
*/
-void fir_design(Float *buffer, int length, Float cutoff)
+static void fir_design(Float *buffer, int length, Float cutoff)
{
int j;
double sum;
--- a/src/rate.c
+++ b/src/rate.c
@@ -18,7 +18,6 @@
#include <math.h>
#include "st.h"
-#include "libst.h"
/*
* Linear Interpolation.
--- a/src/raw.c
+++ b/src/raw.c
@@ -20,12 +20,7 @@
*/
#include "st.h"
-#include "libst.h"
-#ifdef HAVE_MALLOC_H
-#include <malloc.h>
-#endif
-
#include <string.h>
#include <stdlib.h>
@@ -35,6 +30,8 @@
#define MAXWSPEED 1
+static void rawdefaults(P1(ft_t ft));
+
void rawstartread(ft)
ft_t ft;
{
@@ -57,7 +54,7 @@
/* Read raw file data, and convert it to */
/* the sox internal signed long format. */
-unsigned char blockgetc(ft)
+static unsigned char blockgetc(ft)
ft_t ft;
{
char rval;
@@ -78,7 +75,7 @@
return (rval);
}
-/* Util to swap every 2 chars up to 'n' imes. */
+/* Util to reverse the n chars starting at p. */
static void swapn(p, n)
char *p;
int n;
@@ -282,7 +279,7 @@
ft->file.pos = 0;
}
-void blockputc(ft,c)
+static void blockputc(ft,c)
ft_t ft;
int c;
{
@@ -479,8 +476,6 @@
* Set parameters to the fixed parameters known for this format,
* and change format to raw format.
*/
-
-void rawdefaults();
#define STARTREAD(NAME,SIZE,STYLE) \
void NAME(ft) \
--- a/src/resample.c
+++ b/src/resample.c
@@ -37,12 +37,19 @@
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
*
*/
+/*
+ * SJB: [11/25/99]
+ * TODO: another idea for improvement...
+ * note that upsampling usually doesn't require interpolation,
+ * therefore is faster and more accurate than downsampling.
+ * Downsampling by an integer factor is also simple, since
+ * it just involves decimation if the input is already
+ * lowpass-filtered to the output Nyquist freqency.
+ * Get the idea? :)
+ */
#include <math.h>
#include <stdlib.h>
-#ifdef HAVE_MALLOC_H
-#include <malloc.h>
-#endif
#include "st.h"
/* resample includes */
@@ -82,12 +89,13 @@
Float *X, *Y; /* I/O buffers */
} *resample_t;
-void LpFilter(P5(double c[],
+static void LpFilter(P5(double c[],
LONG N,
double frq,
double Beta,
LONG Num));
+/* makeFilter is used by filter.c */
int makeFilter(P5(Float Imp[],
LONG Nwing,
double Froll,
@@ -633,7 +641,7 @@
#define IzeroEPSILON 1E-21 /* Max error acceptable in Izero */
-double Izero(x)
+static double Izero(x)
double x;
{
double sum, u, halfx, temp;
@@ -651,7 +659,7 @@
return(sum);
}
-void LpFilter(c,N,frq,Beta,Num)
+static void LpFilter(c,N,frq,Beta,Num)
double c[], frq, Beta;
LONG N, Num;
{
--- a/src/reverb.c
+++ b/src/reverb.c
@@ -93,12 +93,8 @@
*/
#include <stdlib.h> /* Harmless, and prototypes atof() etc. --dgc */
-#ifdef HAVE_MALLOC_H
-#include <malloc.h>
-#endif
#include <math.h>
#include "st.h"
-#include "libst.h"
#define REVERB_FADE_THRESH 10
#define DELAY_BUFSIZ ( 50L * MAXRATE )
--- a/src/sf.c
+++ b/src/sf.c
@@ -25,9 +25,6 @@
#endif
#include <string.h>
#include <stdlib.h>
-#ifdef HAVE_MALLOC_H
-#include <malloc.h>
-#endif
/* Private data for SF file */
typedef struct sfstuff {
@@ -38,7 +35,7 @@
* Read the codes from the sound file, allocate space for the comment and
* assign its pointer to the comment field in ft.
*/
-void readcodes(ft, sfhead)
+static void readcodes(ft, sfhead)
ft_t ft;
SFHEADER *sfhead;
{
--- a/src/smp.c
+++ b/src/smp.c
@@ -103,7 +103,7 @@
/*
* set the trailer data - loops and markers, to reasonably benign values
*/
-void settrailer(ft, trailer, rate)
+static void settrailer(ft, trailer, rate)
ft_t ft;
struct smptrailer *trailer;
unsigned int rate;
--- a/src/sndrtool.c
+++ b/src/sndrtool.c
@@ -26,8 +26,7 @@
#define SEEK_CUR 1
#endif
-void sndtwriteheader(P2(ft_t ft,LONG nsamples));
-void rawwrite(P3(ft_t, LONG *, LONG));
+static void sndtwriteheader(P2(ft_t ft,LONG nsamples));
/*======================================================================*/
/* SNDSTARTREAD */
@@ -192,7 +191,7 @@
/*======================================================================*/
/* SNDTWRITEHEADER */
/*======================================================================*/
-void sndtwriteheader(ft,nsamples)
+static void sndtwriteheader(ft,nsamples)
ft_t ft;
LONG nsamples;
{
@@ -213,5 +212,4 @@
sprintf (name_buf,"%s - File created by Sound Exchange",ft->filename);
fwrite (name_buf, 1, 96, ft->fp);
}
-
--- a/src/sox.c
+++ b/src/sox.c
@@ -12,6 +12,12 @@
*
* Change History:
*
+ * Nov. 1, 1999 - Stan Brooks (stabro@megsinet.com)
+ * Added -X input option, to extract range of samples.
+ * Moved volume and dovolume from static variables into ft->info...
+ * TODO: This should allow a way (kluge) of specifying multiple
+ * inputs to be mixed together.
+ *
* June 1, 1998 - Chris Bagwell (cbagwell@sprynet.com)
* Added patch to get volume working again. Based on patch sent from
* Matija Nalis <mnalis@public.srce.hr>.
@@ -32,9 +38,6 @@
#include <stdio.h>
#include <string.h>
#include <stdlib.h> /* for malloc() */
-#ifdef HAVE_MALLOC_H
-#include <malloc.h>
-#endif
#include <errno.h>
#include <sys/types.h> /* for fstat() */
#include <sys/stat.h> /* for fstat() */
@@ -64,35 +67,39 @@
* Rewrite for multiple effects: Aug 24, 1994.
*/
-int clipped = 0; /* Volume change clipping errors */
+static int clipped = 0; /* Volume change clipping errors */
+static int writing = 0; /* are we writing to a file? */
+static int soxpreview = 0; /* preview mode */
+
static LONG ibufl[BUFSIZ/2]; /* Left/right interleave buffers */
static LONG ibufr[BUFSIZ/2];
static LONG obufl[BUFSIZ/2];
static LONG obufr[BUFSIZ/2];
-void init();
-void doopts(P2(int, char **));
-void usage(P1(char *));
-int filetype(P1(int));
-void process();
-void statistics();
-LONG volumechange();
-void checkeffect(P1(eff_t));
-int flow_effect(P1(int));
-int drain_effect(P1(int));
+/* local forward declarations */
+static void init(P0);
+static void doopts(P2(int, char **));
+static void usage(P1(char *))NORET;
+static int filetype(P1(int));
+static void process(P0);
+static void statistics(P0);
+static LONG volumechange(P3(LONG *buf, LONG ct, double vol));
+static void checkeffect(P1(eff_t));
+static int flow_effect(P1(int));
+static int drain_effect(P1(int));
-struct soundstream informat, outformat;
+static struct soundstream informat, outformat;
-ft_t ft;
+static ft_t ft;
#define MAXEFF 4
-struct effect eff;
-struct effect efftab[MAXEFF]; /* table of left/mono channel effects */
-struct effect efftabR[MAXEFF]; /* table of right channel effects */
+static struct effect eff;
+static struct effect efftab[MAXEFF]; /* table of left/mono channel effects */
+static struct effect efftabR[MAXEFF]; /* table of right channel effects */
/* efftab[0] is the input stream */
-int neffects; /* # of effects */
-char *ifile, *ofile, *itype, *otype;
+static int neffects; /* # of effects */
+static char *ifile, *ofile;
int main(argc, argv)
int argc;
@@ -105,6 +112,7 @@
/* Get input format options */
ft = &informat;
+ clipped = 0;
doopts(argc, argv);
/* Get input file */
if (optind >= argc)
@@ -172,8 +180,8 @@
}
/* Check global arguments */
- if (volume <= 0.0)
- fail("Volume must be greater than 0.0");
+ if (informat.info.dovol && informat.info.vol == 0.0)
+ fail("Volume must be non-zero"); /* negative volume is phase-reversal */
/* If file types have not been set with -t, set from file names. */
if (! informat.filetype) {
@@ -206,12 +214,12 @@
}
#ifdef HAVE_GETOPT_H
-char *getoptstr = "+r:v:t:c:phsuUAaigbwlfdDxV";
+static char *getoptstr = "+r:v:t:c:B:X:phsuUAaigbwlfdDxV";
#else
-char *getoptstr = "r:v:t:c:phsuUAaigbwlfdDxV";
+static char *getoptstr = "r:v:t:c:B:X:phsuUAaigbwlfdDxV";
#endif
-void doopts(argc, argv)
+static void doopts(argc, argv)
int argc;
char **argv;
{
@@ -234,13 +242,16 @@
if (ft->filetype[0] == '.')
ft->filetype++;
break;
-#if 0
+
case 'X': /* extract a subinterval of samples as input */
if (! ft) usage("-X");
- ft->fileextract++;
- ft->filetype = optarg;
+ str = optarg;
+ /* FIXME: allow "A-B" "-B" "A-" "A,B" also maybe lists of ranges */
+ if ( 2 != sscanf(str, "%lu-%lu", &ft->info.x0, &ft->info.x1))
+ fail("eXtract range '%s' is not valid", optarg);
+ if (ft->info.x1==0) ft->info.x1 -= 1; /* MAXULONG */
break;
-#endif
+
case 'r':
if (! ft) usage("-r");
str = optarg;
@@ -254,13 +265,11 @@
fail("-r must be given a positive integer");
break;
case 'v':
- if (! ft) usage("-v");
+ if (!ft || ft->info.dovol) usage("-v");
str = optarg;
- if ((! sscanf(str, "%e", &volume)) ||
- (volume <= 0))
- fail("Volume value '%s' is not a number",
- optarg);
- dovolume = 1;
+ if (! sscanf(str, "%lf", &ft->info.vol)) /* neg volume is ok */
+ fail("Volume value '%s' is not a number", optarg);
+ ft->info.dovol = 1;
break;
case 'c':
@@ -269,6 +278,12 @@
if (! sscanf(str, "%d", &ft->info.channels))
fail("-c must be given a number");
break;
+ case 'B':
+ if (! ft) usage("-B");
+ str = optarg;
+ if (! sscanf(str, "%hu", &ft->info.bs) || ft->info.bs<=0) /* blocksize */
+ fail("-B must be given a positive number");
+ break;
case 'b':
if (! ft) usage("-b");
ft->info.size = BYTE;
@@ -335,7 +350,7 @@
}
}
-void init() {
+static void init(P0) {
/* init files */
informat.info.rate = outformat.info.rate = 0;
@@ -342,6 +357,12 @@
informat.info.size = outformat.info.size = -1;
informat.info.style = outformat.info.style = -1;
informat.info.channels = outformat.info.channels = -1;
+ informat.info.bs = outformat.info.bs = 0;
+ informat.info.dovol = outformat.info.dovol = 0;
+ informat.info.vol = outformat.info.vol = 1.0;
+ informat.info.x = outformat.info.x = 0;
+ informat.info.x0 = outformat.info.x0 = 0;
+ informat.info.x1 = outformat.info.x1 = -1;
informat.comment = outformat.comment = NULL;
informat.swap = 0;
informat.filetype = outformat.filetype = (char *) 0;
@@ -356,7 +377,7 @@
* one buffer at a time
*/
-void process() {
+static void process(P0) {
LONG i;
int e, f, havedata;
@@ -368,8 +389,10 @@
(* informat.h->startread)(&informat);
checkformat(&informat);
- if (dovolume)
- report("Volume factor: %f\n", volume);
+ if (informat.info.dovol)
+ report("Volume factor: %f\n", informat.info.vol);
+ if (informat.info.x0 || informat.info.x1 != MAXULONG)
+ report("Extract samples %lu <= x < %lu\n", informat.info.x0, informat.info.x0);
report("Input file: using sample rate %lu\n\tsize %s, style %s, %d %s",
informat.info.rate, sizes[informat.info.size],
@@ -461,19 +484,26 @@
efftabR[e].obuf = (LONG *) malloc(BUFSIZ * sizeof(LONG));
}
- /* Read initial chunk of input data. */
- efftab[0].olen = (*informat.h->read)(&informat,
- efftab[0].obuf, (LONG) BUFSIZ);
- efftab[0].odone = 0;
- /* Change the volume of this initial input data if needed. */
- if (dovolume)
- for (i = 0; i < efftab[0].olen; i++)
- efftab[0].obuf[i] = volumechange(efftab[0].obuf[i]);
-
/* Run input data through effects and get more until olen == 0 */
- while (efftab[0].olen > 0) {
+ while (informat.info.x < informat.info.x1) {
+ ULONG ct, r;
+ /* Read (extracted) chunk of input data. */
+ ct = (informat.info.x < informat.info.x0)?
+ (informat.info.x0 - informat.info.x) : (informat.info.x1 - informat.info.x);
+ if (ct > BUFSIZ) ct = BUFSIZ;
+ r = (*informat.h->read)(&informat, efftab[0].obuf, ct);
+ if (!r) break;
+ informat.info.x += r;
+ if (informat.info.x <= informat.info.x0) continue;
+ efftab[0].olen = r;
+ efftab[0].odone = 0;
+
+ /* Change the volume of this initial input data if needed. */
+ if (informat.info.dovol)
+ clipped += volumechange(efftab[0].obuf, efftab[0].olen, informat.info.vol);
+
/* mark chain as empty */
for(e = 1; e < neffects; e++)
efftab[e].odone = efftab[e].olen = 0;
@@ -502,15 +532,6 @@
}
} while (havedata);
- /* Read another chunk of input data. */
- efftab[0].olen = (*informat.h->read)(&informat,
- efftab[0].obuf, (LONG) BUFSIZ);
- efftab[0].odone = 0;
-
- /* Change volume of these samples if needed. */
- if (dovolume)
- for (i = 0; i < efftab[0].olen; i++)
- efftab[0].obuf[i] = volumechange(efftab[0].obuf[i]);
}
/* Drain the effects out first to last,
@@ -553,7 +574,7 @@
fclose(outformat.fp);
}
-int flow_effect(e)
+static int flow_effect(e)
int e;
{
LONG i, done, idone, odone, idonel, odonel, idoner, odoner;
@@ -617,7 +638,7 @@
return 1;
}
-int drain_effect(e)
+static int drain_effect(e)
int e;
{
LONG i, olen, olenl, olenr;
@@ -671,7 +692,7 @@
* Smart ruleset for multiple effects in sequence.
* Puts user-specified effect in right place.
*/
-void
+static void
checkeffect(effp)
eff_t effp;
{
@@ -849,30 +870,38 @@
}
/* Guido Van Rossum fix */
-void statistics() {
- if (dovolume && clipped > 0)
+static void statistics(P0) {
+ if (informat.info.dovol && clipped > 0)
report("Volume change clipped %d samples", clipped);
}
-LONG volumechange(y)
-LONG y;
+static LONG volumechange(buf, ct, vol)
+LONG *buf;
+LONG ct;
+double vol;
{
- double y1;
+ double y;
+ LONG *p,*top;
+ LONG clips=0;
- y1 = y * volume;
- if (y1 < -2147483647.0) {
- y1 = -2147483647.0;
- clipped++;
+ p = buf;
+ top = buf+ct;
+ while (p < top) {
+ y = vol * *p;
+ if (y < -2147483647.0) {
+ y = -2147483647.0;
+ clips++;
+ }
+ else if (y > 2147483647.0) {
+ y = 2147483647.0;
+ clips++;
+ }
+ *p++ = y + 0.5;
}
- else if (y1 > 2147483647.0) {
- y1 = 2147483647.0;
- clipped++;
- }
-
- return y1;
+ return clips;
}
-int filetype(fd)
+static int filetype(fd)
int fd;
{
struct stat st;
@@ -882,10 +911,10 @@
return st.st_mode & S_IFMT;
}
-char *usagestr =
+static char *usagestr =
"[ gopts ] [ fopts ] ifile [ fopts ] ofile [ effect [ effopts ] ]";
-void usage(opt)
+static void usage(opt)
char *opt;
{
int i;
@@ -916,7 +945,7 @@
/* called from util.c:fail */
-void cleanup() {
+void cleanup(P0) {
/* Close the input file and outputfile before exiting*/
if (informat.fp)
fclose(informat.fp);
--- a/src/st.h
+++ b/src/st.h
@@ -12,12 +12,20 @@
*/
#include <stdio.h>
-
+#include <stdlib.h>
+#ifdef HAVE_MALLOC_H
+#include <malloc.h>
+#endif
#ifdef HAVE_BYTESWAP_H
#include <byteswap.h>
#endif
-/* FIXME: Move to seperate header */
+
+/* SJB: these may be changed to assist fail-recovery in libST */
+#define st_malloc malloc
+#define st_free free
+
+/* FIXME: Move to separate header */
#ifdef __alpha__
#include <sys/types.h> /* To get defines for 32-bit integers */
#define LONG int32_t
@@ -27,11 +35,17 @@
#define ULONG unsigned long
#endif
+#define MAXLONG 0x7fffffffL
+#define MAXULONG 0xffffffff
+
+/* various gcc optimizations */
#ifdef __GNUC__
#define NORET __attribute__((noreturn))
+#define REGPARM(n) __attribute__((regparm(n)))
#define INLINE inline
#else
#define NORET
+#define REGPARM(n)
#define INLINE
#endif
@@ -61,6 +75,12 @@
int size; /* word length of data */
int style; /* format of sample numbers */
int channels; /* number of sound channels */
+ unsigned short bs; /* requested blocksize, eg for output .wav's */
+ unsigned char dovol; /* has volume factor */
+ double vol; /* volume factor */
+ ULONG x; /* current sample number */
+ ULONG x0; /* 1st sample (if source) */
+ ULONG x1; /* top sample (if source) */
};
/* Loop parameters */
@@ -134,10 +154,6 @@
double priv[PRIVSIZE/8]; /* format's private data area */
};
-/* This shoul not be here. Only needed in sox.c */
-extern struct soundstream informat;
-extern struct soundstream outformat;
-
typedef struct soundstream *ft_t;
/* FIXME: Prefix all #defines with ST_ */
@@ -146,7 +162,7 @@
#define FILE_LOOPS 2 /* does file format support loops? */
#define FILE_INSTR 4 /* does file format support instrument specificications? */
-/* Size field */
+/* Size field */ /* SJB: note that the 1st 3 are sometimes used as sizeof(type) */
#define BYTE 1
#define WORD 2
#define DWORD 4
@@ -166,8 +182,9 @@
/* FIXME: This shouldn't be defined inside library. Only needed
* by sox.c itself. Delete from raw.c and misc.c.
*/
-extern char *sizes[];
-extern char *styles[];
+/* declared in misc.c */
+extern const char *sizes[];
+extern const char *styles[];
/*
* Handler structure for each effect.
@@ -183,7 +200,7 @@
void (*stop)(); /* finish up effect */
} effect_t;
-extern effect_t effects[];
+extern effect_t effects[]; /* declared in handlers.c */
#define EFF_CHAN 1 /* Effect can mix channels up/down */
#define EFF_RATE 2 /* Effect can alter data rate */
@@ -206,6 +223,7 @@
/* FIXME: Move to internal st header */
#if defined(__STDC__)
+#define P0 void
#define P1(a) a
#define P2(a,b) a, b
#define P3(a,b,c) a, b, c
@@ -217,6 +235,7 @@
#define P9(a,b,c,d,e,f,g,h,i) a, b, c, d, e, f, g, h, i
#define P10(a,b,c,d,e,f,g,h,i,j) a, b, c, d, e, f, g, h, i, j
#else
+#define P0
#define P1(a)
#define P2(a,b)
#define P3(a,b,c)
@@ -229,9 +248,31 @@
#define P10(a,b,c,d,e,f,g,h,i,j)
#endif
+/* declared in misc.c */
+extern LONG st_clip24(P1(LONG)) REGPARM(1);
+extern void st_sine(P4(int *, LONG, int, int));
+extern void st_triangle(P4(int *, LONG, int, int));
+
+extern LONG st_gcd(P2(LONG,LONG)) REGPARM(2);
+extern LONG st_lcm(P2(LONG,LONG)) REGPARM(2);
+/****************************************************/
+/* Prototypes for internal cross-platform functions */
+/****************************************************/
+/* SJB: shouldn't these be elsewhere, exported from misc.c */
+#ifndef HAVE_RAND
+extern int rand(P0);
+extern void srand(P1(ULONG seed));
+#endif
+extern void st_initrand(P0);
+
+#ifndef HAVE_STRERROR
+char *strerror(P1(int errorcode));
+#endif
+
/* Read and write basic data types from "ft" stream. Uses ft->swap for
* possible byte swapping.
*/
+/* declared in misc.c */
unsigned short rshort(P1(ft_t ft));
unsigned short wshort(P2(ft_t ft, unsigned short us));
ULONG rlong(P1(ft_t ft));
@@ -245,6 +286,7 @@
* here for convience. This wont last for long so application software
* shouldn't make use of it.
*/
+/* declared in raw.c */
void rawstartread(P1(ft_t ft));
void rawstartwrite(P1(ft_t ft));
void rawstopread(P1(ft_t ft));
@@ -265,9 +307,9 @@
double swapd(P1(double d)); /* Swap double */
/* util.c */
-void report(P2(char *, ...));
-void warn(P2(char *, ...));
-void fail(P2(char *, ...))NORET;
+void report(P2(const char *, ...));
+void warn(P2(const char *, ...));
+void fail(P2(const char *, ...))NORET;
void geteffect(P1(eff_t));
void gettype(P1(ft_t));
@@ -281,23 +323,11 @@
*/
void sigintreg(P1(ft_t));
-/* FIXME: Move to sox header file. */
-typedef unsigned int u_i;
-typedef ULONG u_l;
-typedef unsigned short u_s;
-
-extern float volume; /* expansion coefficient */
-extern int dovolume;
-
-extern int writing; /* are we writing to a file? */
-
/* export flags */
+/* FIXME: these declared in util.c, inappropriate for lib */
extern int verbose; /* be noisy on stderr */
-
extern char *myname;
-extern int soxpreview; /* Preview mode: be fast and ugly */
-
/* FIXME: Not externally visible currently. Its a per-effect value. */
#define MAXRATE 50L * 1024 /* maximum sample rate */
@@ -314,6 +344,6 @@
#define REMOVE unlink
-char *version(); /* return version number */
+const char *version(P0); /* return version number */
#endif
--- a/src/stat.c
+++ b/src/stat.c
@@ -18,8 +18,6 @@
#include <math.h>
#include "st.h"
-#define MAXLONG 0x7fffffffL
-
/* Private data for STAT effect */
typedef struct statstuff {
double min, max;
--- a/src/sunaudio.c
+++ b/src/sunaudio.c
@@ -26,12 +26,8 @@
#include <malloc.h>
#include <unistd.h>
#include <stdlib.h>
-#ifdef HAVE_MALLOC_H
-#include <malloc.h>
-#endif
#include <fcntl.h>
#include "st.h"
-#include "libst.h"
/*
* Do anything required before you start reading samples.
--- a/src/tx16w.c
+++ b/src/tx16w.c
@@ -60,9 +60,10 @@
unused[2]; /* set these to null, to be on the safe side */
} ;
-static unsigned char magic1[4] = {0, 0x06, 0x10, 0xF6};
-static unsigned char magic2[4] = {0, 0x52, 0x00, 0x52};
+static const unsigned char magic1[4] = {0, 0x06, 0x10, 0xF6};
+static const unsigned char magic2[4] = {0, 0x52, 0x00, 0x52};
+/* SJB: dangerous static variables */
static LONG tx16w_len=0;
static LONG writedone=0;
--- a/src/util.c
+++ b/src/util.c
@@ -28,22 +28,15 @@
* and utility routines for other main programs to use.
*/
-
-float volume = 1.0; /* expansion coefficient */
-int dovolume = 0;
-
-int writing = 0; /* are we writing to a file? */
-
/* export flags */
int verbose = 0; /* be noisy on stderr */
char *myname = 0;
-int soxpreview = 0; /* preview mode */
void
-report(char *fmt, ...)
+report(const char *fmt, ...)
{
va_list args;
@@ -59,7 +52,7 @@
void
-warn(char *fmt, ...)
+warn(const char *fmt, ...)
{
va_list args;
@@ -72,7 +65,7 @@
}
void
-fail(char *fmt, ...)
+fail(const char *fmt, ...)
{
va_list args;
extern void cleanup();
--- a/src/vibro.c
+++ b/src/vibro.c
@@ -26,9 +26,6 @@
#include <math.h>
#include <stdlib.h>
-#ifdef HAVE_MALLOC_H
-#include <malloc.h>
-#endif
#include "st.h"
/* Private data for Vibro effect */
@@ -62,7 +59,7 @@
/* This was very painful. We need a sine library. */
-void sine(buf, len, depth)
+static void sine(buf, len, depth)
short *buf;
int len;
float depth;
--- a/src/voc.c
+++ b/src/voc.c
@@ -167,9 +167,9 @@
#define min(a, b) (((a) < (b)) ? (a) : (b))
-void getblock();
-void blockstart(P1(ft_t));
-void blockstop(P1(ft_t));
+static void getblock(P1(ft_t));
+static void blockstart(P1(ft_t));
+static void blockstop(P1(ft_t));
void vocstartread(ft)
ft_t ft;
@@ -346,7 +346,7 @@
/* Voc-file handlers */
/* Read next block header, save info, leave position at start of data */
-void
+static void
getblock(ft)
ft_t ft;
{
@@ -503,7 +503,7 @@
}
/* Start an output block. */
-void blockstart(ft)
+static void blockstart(ft)
ft_t ft;
{
vs_t v = (vs_t) ft->priv;
@@ -559,7 +559,7 @@
}
/* End the current data or silence block. */
-void blockstop(ft)
+static void blockstop(ft)
ft_t ft;
{
vs_t v = (vs_t) ft->priv;
--- a/src/wav.c
+++ b/src/wav.c
@@ -61,9 +61,6 @@
#include <string.h> /* Included for strncmp */
#include <stdlib.h> /* Included for malloc and free */
-#ifdef HAVE_MALLOC_H
-#include <malloc.h>
-#endif
#include <stdio.h>
#ifdef HAVE_UNISTD_H
@@ -83,7 +80,8 @@
/* Private data for .wav file */
typedef struct wavstuff {
- LONG numSamples;
+ LONG numSamples; /* reading: starts at total count and decremented */
+ /* writing: starts at 0 and counts samples written */
LONG dataLength; /* needed for ADPCM writing */
unsigned short formatTag; /* What type of encoding file is using */
unsigned short samplesPerBlock;
@@ -101,10 +99,10 @@
/* following used by GSM 6.10 wav */
#ifdef HAVE_LIBGSM
- gsm gsmhandle;
- gsm_signal *gsmsample;
- int gsmindex;
- int gsmbytecount;
+ gsm gsmhandle;
+ gsm_signal *gsmsample;
+ int gsmindex;
+ int gsmbytecount; /* counts bytes written to data block */
#endif
} *wav_t;
@@ -116,9 +114,7 @@
static char *wav_format_str();
-LONG rawread(P3(ft_t, LONG *, LONG));
-void rawwrite(P3(ft_t, LONG *, LONG));
-void wavwritehdr(P2(ft_t, int));
+static void wavwritehdr(P2(ft_t, int));
/****************************************************************************/
@@ -282,7 +278,7 @@
wav_t wav = (wav_t) ft->priv;
int done=0;
int bytes;
- gsm_frame frame;
+ gsm_byte frame[65];
/* copy out any samples left from the last call */
while(wav->gsmindex && (wav->gsmindex<160*2) && (done < len))
@@ -291,25 +287,20 @@
/* read and decode loop, possibly leaving some samples in wav->gsmsample */
while (done < len) {
wav->gsmindex=0;
- /*read the long 33 byte half */
- bytes = fread(frame,1,sizeof(frame),ft->fp);
+ bytes = fread(frame,1,65,ft->fp);
if (bytes <=0)
return done;
- if (bytes<sizeof(frame))
- fail("invalid wav gsm frame size: %d bytes",bytes);
+ if (bytes<65) {
+ warn("invalid wav gsm frame size: %d bytes",bytes);
+ return done;
+ }
+ /* decode the long 33 byte half */
if(gsm_decode(wav->gsmhandle,frame, wav->gsmsample)<0)
fail("error during gsm decode");
-
- /*read the short 32 byte half */
- bytes = fread(frame,1,sizeof(frame)-1,ft->fp);
- if (bytes <=0)
- return done;
- if (bytes<sizeof(frame)-1)
- fail("invalid wav gsm frame size: %d bytes",bytes);
- if(gsm_decode(wav->gsmhandle,frame, &(wav->gsmsample[160]))<0)
+ /* decode the short 32 byte half */
+ if(gsm_decode(wav->gsmhandle,frame+33, wav->gsmsample+160)<0)
fail("error during gsm decode");
-
while ((wav->gsmindex <160*2) && (done < len)){
buf[done++]=LEFT(wav->gsmsample[(wav->gsmindex)++],16);
}
@@ -318,35 +309,50 @@
return done;
}
+static void wavgsmflush(ft, pad)
+ft_t ft;
+int pad; /* normally 0, but 1 to pad last write to even datalen */
+{
+ gsm_byte frame[65];
+ wav_t wav = (wav_t) ft->priv;
+
+ /* zero fill as needed */
+ while(wav->gsmindex<160*2)
+ wav->gsmsample[wav->gsmindex++]=0;
+
+ /*encode the even half short (32 byte) frame */
+ gsm_encode(wav->gsmhandle, wav->gsmsample, frame);
+ /*encode the odd half long (33 byte) frame */
+ gsm_encode(wav->gsmhandle, wav->gsmsample+160, frame+32);
+ if (fwrite(frame, 1, 65, ft->fp) != 65)
+ fail("write error");
+ wav->gsmbytecount += 65;
+
+ wav->gsmindex = 0;
+
+ if (pad & wav->gsmbytecount){
+ /* pad output to an even number of bytes */
+ if(fputc(0,ft->fp))
+ fail("write error");
+ wav->gsmbytecount += 1;
+ }
+}
+
void wavgsmwrite(ft, buf, len)
ft_t ft;
LONG *buf, len;
{
wav_t wav = (wav_t) ft->priv;
-
int done = 0;
- gsm_frame frame;
while (done < len) {
- while ((wav->gsmindex < 160*2) && (done < len)){
+ while ((wav->gsmindex < 160*2) && (done < len))
wav->gsmsample[(wav->gsmindex)++] = RIGHT(buf[done++], 16);
- }
- if (wav->gsmindex < 160*2){
- return;
- }
- /*encode the even half and write short (32 byte) frame */
- gsm_encode(wav->gsmhandle, wav->gsmsample, frame);
- if (fwrite(frame, 1, sizeof(frame)-1, ft->fp) != sizeof(frame)-1)
- fail("write error");
- wav->gsmbytecount += sizeof(frame)-1;
+ if (wav->gsmindex < 160*2)
+ break;
- /*encode the odd half and write long (33 byte) frame */
- gsm_encode(wav->gsmhandle, &(wav->gsmsample[160]), frame);
- if (fwrite(frame, 1, sizeof(frame), ft->fp) != sizeof(frame))
- fail("write error");
- wav->gsmbytecount += sizeof(frame);
- wav->gsmindex = 0;
+ wavgsmflush(ft, 0);
}
}
@@ -354,32 +360,11 @@
void wavgsmstopwrite(ft)
ft_t ft;
{
- gsm_frame frame;
wav_t wav = (wav_t) ft->priv;
- if (wav->gsmindex){
- while(wav->gsmindex<160*2){
- wav->gsmsample[wav->gsmindex++]=0;
- }
- /*encode the even half and write short (32 byte) frame */
- gsm_encode(wav->gsmhandle, wav->gsmsample, frame);
- if (fwrite(frame, 1, sizeof(frame)-1, ft->fp) != sizeof(frame)-1)
- fail("write error");
- wav->gsmbytecount += sizeof(frame)-1;
-
- /*encode the odd half and write long (33 byte) frame */
- gsm_encode(wav->gsmhandle, &(wav->gsmsample[160]), frame);
- if (fwrite(frame, 1, sizeof(frame), ft->fp) != sizeof(frame))
- fail("write error");
- wav->gsmbytecount += sizeof(frame);
+ if (wav->gsmindex)
+ wavgsmflush(ft, 1);
- /* pad output to an even number of bytes */
- if (wav->gsmbytecount & 0x1){
- if(fputc(0,ft->fp))
- fail("write error");
- wav->gsmbytecount += 1;
- }
- }
wavgsmdestroy(ft);
}
#endif /*ifdef out gsm code */
@@ -848,9 +833,8 @@
top = p+ct;
/* Output is already signed */
while (p<top)
- {
*buf++ = LEFT((*p++), 16);
- }
+
wav->samplePtr = p;
}
}
@@ -863,7 +847,7 @@
warn("Premature EOF on .wav input file");
break;
#endif
- default: /* not ADPCM style */
+ default: /* assume PCM style */
done = rawread(ft, buf, len);
/* If software thinks there are more samples but I/O */
/* says otherwise, let the user know about this. */
@@ -1007,7 +991,7 @@
*/
-void wavwritehdr(ft, second_header)
+static void wavwritehdr(ft, second_header)
ft_t ft;
int second_header;
{
--- a/src/wve.c
+++ b/src/wve.c
@@ -19,7 +19,7 @@
short repeats;
};
-void wvewriteheader(P1(ft_t ft));
+static void wvewriteheader(P1(ft_t ft));
void wvestartread(ft)
ft_t ft;
@@ -165,7 +165,7 @@
rawstopwrite(ft);
}
-void wvewriteheader(ft)
+static void wvewriteheader(ft)
ft_t ft;
{
--- a/test/ding.c
+++ b/test/ding.c
@@ -43,14 +43,83 @@
#endif
struct _Env {
- int r; /* rise */
- int m; /* middle */
- int f; /* fall */
- int e; /* end */
- FLOAT v; /* volume */
- FLOAT d; /* decay */
-} Env = {0,0,0,0,0.5,1.0};
+ struct _Env *next;
+ int r; /* rise */
+ int m; /* middle */
+ int f; /* fall */
+ int e; /* end */
+ FLOAT frq; /* frequency */
+ FLOAT b; /* bend (not quite implemented) */
+ FLOAT v; /* volume */
+ FLOAT d; /* decay */
+ FLOAT x,y; /* current x,y */
+ FLOAT phx,phy;/* per-sample phase multiplier cos(PI*frq),sin(PI*frq) */
+};
+const struct _Env EnvTemplate = {NULL,0,0,0,0,0.0,0.0,0.5,1.0,0.0,1.0,1.0,0.0};
+
+struct _Env * Env0 = NULL; /* 1st */
+struct _Env * EnvL = NULL; /* last */
+
+struct _Env *env_new(struct _Env *L)
+{
+ struct _Env *E;
+ E = (struct _Env *) malloc(sizeof(struct _Env));
+ if (E) {
+ memcpy(E, (L)? L : &EnvTemplate, sizeof(struct _Env));
+ }
+ return E;
+}
+
+static void env_init(struct _Env *E)
+{
+ if (0<E->frq && E->frq<1) {
+ E->x = 1; E->y = 0;
+ } else {
+ E->x = 0; E->y = 1;
+ }
+ E->phx = cos(E->frq*M_PI);
+ E->phy = sin(E->frq*M_PI);
+}
+
+static void env_post(struct _Env *E, int k)
+{
+ double x1;
+ x1 = E->x*E->phx - E->y*E->phy;
+ E->y = E->x*E->phy + E->y*E->phx;
+ E->x = x1;
+ /* update (x,y) for next tic */
+ if (!(k&0x0f)) { /* norm correction each 16 samples */
+ x1 = 1/sqrt(E->x*E->x+E->y*E->y);
+ E->x *= x1;
+ E->y *= x1;
+ }
+}
+
+/* rise/fall function, monotonic [0,1] -> [1-0] */
+static inline double ramp(double s)
+{
+ return 0.5*(1 + cos(M_PI * s));
+}
+
+static double env(struct _Env *Env, int k)
+{
+ double u = 0;
+ //if (k >= Env->r && k < Env->e) {
+ if (k<Env->m) {
+ u = Env->v * ramp((double)(Env->m-k)/(Env->m-Env->r));
+ }else if (k<Env->f) {
+ u = Env->v;
+ Env->v *= Env->d;
+ }else{
+ u = Env->v * ramp((double)(k-Env->f)/(Env->e-Env->f));
+ }
+ u *= Env->y;
+ env_post(Env,k);
+ //}
+ return u;
+}
+
static void Usage(void)__attribute__((noreturn));
static void Usage(void)
@@ -57,12 +126,10 @@
{
fprintf(stderr, "Usage: ./ding [options] [<in-file>] <out-file>\n");
fprintf(stderr, " Options:\n");
+ fprintf(stderr, " -f <freq> float, frequency = freq*nyquist_rate\n");
fprintf(stderr, " [-v <vol>] float, volume, 1.00 is max\n");
- fprintf(stderr, " [-f <freq>] float, frequency = freq*nyquist_rate\n");
fprintf(stderr, " [-d <decay>] float, per-sample decay factor\n");
- fprintf(stderr, " [-o <n>] int, zero-pad samples before tone\n");
- fprintf(stderr, " [-e <n>] int, length in samples of tone\n");
- fprintf(stderr, " [-p <n>] int, zero-pad samples after tone\n");
+ fprintf(stderr, " [-e start:attack:duration:mute] ints \n");
exit(-1);
}
@@ -109,63 +176,20 @@
SAMPL *ibuff,max,min;
int poflo,moflo;
FLOAT Vol0=1;
- FLOAT Freq=0; /* of nyquist */
- int Pad=0;
- double x=1,y=0;
- double thx=1,thy=0;
-
- static inline void a_init(double frq)
- {
- if (0<frq && frq<1) {
- x = 1; y = 0;
- } else {
- x = 0; y = 1;
- }
- thx = cos(frq*M_PI);
- thy = sin(frq*M_PI);
- }
-
- static inline void a_post(int k)
- {
- double x1;
- x1 = x*thx - y*thy;
- y = x*thy + y*thx;
- x = x1;
- /* update (x,y) for next tic */
- if (!(k&0x0f)) { /* norm correction each 16 samples */
- x1 = 1/sqrt(x*x+y*y);
- x *= x1;
- y *= x1;
- }
- }
+ struct _Env *E;
- /* rise/fall function, monotonic [0,1] -> [1-0] */
- static inline const double a(double s)
- {
- return 0.5*(1 + cos(M_PI * s));
- }
-
- static double env(struct _Env *Env, int k)
- {
- double u = 0;
- //if (k >= Env->r && k < Env->e) {
- if (k<Env->m) {
- u = Env->v * a((double)(Env->m-k)/(Env->m-Env->r));
- }else if (k<Env->f) {
- u = Env->v;
- }else{
- u = Env->v * a((double)(k-Env->f)/(Env->e-Env->f));
- }
- //}
- return u;
- }
-
/* Parse the options */
- while ((optc = getopt(argct, argv, "d:o:e:t:p:f:v:h")) != -1) {
+ E = NULL;
+ len = 0;
+ while ((optc = getopt(argct, argv, "d:e:f:v:h")) != -1) {
char *p;
switch(optc) {
case 'd':
- Env.d = strtod(optarg,&p);
+ if (!E) {
+ fprintf(stderr,"option -f must precede -%c\n", optc);
+ Usage();
+ }
+ E->d = strtod(optarg,&p);
if (p==optarg || *p) {
fprintf(stderr,"option -%c expects float value (%s)\n", optc, optarg);
Usage();
@@ -172,7 +196,12 @@
}
break;
case 'f':
- Freq = strtod(optarg,&p);
+ E = env_new(EnvL);
+ if (EnvL) EnvL->next = E;
+ EnvL = E;
+ if (!Env0) Env0 = E;
+
+ E->frq = strtod(optarg,&p);
if (p==optarg || *p) {
fprintf(stderr,"option -%c expects float value (%s)\n", optc, optarg);
Usage();
@@ -179,36 +208,47 @@
}
break;
case 'e':
- p = optarg;
- Env.f = strtol(p,&p,10);
- if (*p++ == ':') {
- Env.m = Env.e = Env.f;
- Env.f = strtol(p,&p,10);
+ {
+ int t[5], tmin=0;
+ int i,ct=0;
+
+ if (!E) {
+ fprintf(stderr,"option -f must precede -%c\n", optc);
+ Usage();
}
- if (*p++ == ':') {
- Env.e = strtol(p,&p,10);
+ for (p=optarg,ct=0; ct<5; p++) {
+ t[ct] = 0;
+ if (*p && *p != ':') {
+ t[ct] = strtol(p,&p,10);
+ if (t[ct]<tmin) tmin=t[ct];
+ }
+ ct++;
+ if (*p != ':') break;
}
- if (*p || Env.f<=0 || Env.m<0 || Env.e<0) {
+ if (ct==4) t[ct++] = 0;
+
+ if (*p || tmin<0 || ct!=5) {
fprintf(stderr,"option -%c not valid (%s)\n", optc, optarg);
Usage();
}
+
+ for (i=1; i<ct; i++)
+ t[i] += t[i-1];
+
+ E->r = t[0];
+ E->m = t[1];
+ E->f = t[2];
+ E->e = t[3];
+ if (len<t[4]) len=t[4];
break;
- case 'o':
- Env.r = strtol(optarg,&p,10);
- if (p==optarg || *p || Env.r<0) {
- fprintf(stderr,"option -%c expects int value (%s)\n", optc, optarg);
- Usage();
}
- break;
- case 'p':
- Pad = strtol(optarg,&p,10);
- if (p==optarg || *p || Pad<0) {
- fprintf(stderr,"option -%c expects int value (%s)\n", optc, optarg);
+ case 'v':
+ if (!E) {
+ fprintf(stderr,"option -f must precede -%c\n", optc);
Usage();
}
- break;
- case 'v':
- Env.v = strtod(optarg,&p);
+ E->v = MAXSAMPL*strtod(optarg,&p);
+ if (E->frq==0.0) E->v *= sqrt(0.5);
if (p==optarg || *p) {
fprintf(stderr,"option -%c expects float value (%s)\n", optc, optarg);
Usage();
@@ -220,24 +260,20 @@
}
}
- Env.v *= MAXSAMPL;
- if (Freq==0.0) Env.v *= sqrt(0.5);
//fprintf(stderr,"Vol0 %8.3f\n", Vol0);
- Env.m += Env.r;
- Env.f += Env.m;
- Env.e += Env.f;
- len = Env.e+Pad;
fnam1=NULL; fd1=-1;
//fprintf(stderr,"optind=%d argct=%d\n",optind,argct);
if (optind <= argct-2) {
+ int ln1;
fnam1=argv[optind++];
fd1=open(fnam1,O_RDONLY);
if (fd1<0) {
fprintf(stderr,"Open: %s %s\n",fnam1,strerror(errno)); return(1);
}
- len=lseek(fd1,0,SEEK_END)/2;
+ ln1=lseek(fd1,0,SEEK_END)/2;
lseek(fd1,0,SEEK_SET);
+ if (len<ln1) len = ln1;
}
if (optind != argct-1) Usage();
@@ -252,7 +288,7 @@
}
//fprintf(stderr, "Files: %s %s\n",fnam1,fnam2);
- a_init(Freq);
+ for (E=Env0; (E); E=E->next) env_init(E);
ibuff=(SAMPL*)malloc(BSIZ*sizeof(SAMPL));
poflo=moflo=0;
@@ -270,9 +306,10 @@
else if (min>*ibp) min=*ibp;
v *= Vol0;
- if (st>=Env.r && st<Env.e) {
- v += y*env(&Env,st);
- a_post(st);
+ for (E=Env0; (E); E=E->next) {
+ if (st>=E->r && st<E->e) {
+ v += env(E, st);
+ }
}
if (v>MAXSAMPL) {
--- a/test/ltest.pl
+++ b/test/ltest.pl
@@ -33,7 +33,7 @@
my ($rate0,$rate1)=(8000,22050); # sample rates
my $p=400; # silence before/after tonepulse
-my $env="-e4000:16000:4000"; # attack, duration, drop
+my $env="4000:16000:4000"; # attack, duration, drop
#my ($rate0,$rate1)=(22050,8000); # sample rates
#my $p=1102; # silence before/after tonepulse
@@ -71,7 +71,7 @@
}
}
print("# with tone pulses from 0.00 to 0.99 percent of Nyquist\n");
-print("# produced by $ding -f0.xx -v0.5 -o$p $env -p$p d/i0.xx.$t\n");
+print("# produced by $ding -f0.xx -v0.5 -o$p -e$p:$env:$p d/i0.xx.$t\n");
# generate the test data
mkdir("d",0775);
@@ -83,18 +83,18 @@
#if ($f>0.995) { $f=0.999; }
my $s=sprintf("%4.2f",$f);
- #print "$ding -v0.5 -o$p $env -p$p -f$s -d1.0 d/i$s.$t\n";
- qx{$ding -v0.5 -o$p $env -p$p -f$s -d1.0 d/i$s.$t &>/dev/null};
+ #print "$ding -v0.5 -e$p:$env:$p -f$s -d1.0 d/i$s.$t\n";
+ qx{$ding -v0.5 -e$p:$env:$p -f$s -d1.0 d/i$s.$t &>/dev/null};
if ($ratechange==0) {
qx{$sox -r$rate0 d/i$s.$t -r$rate0 d/j$s.$t $effect 2>/dev/null};
- @mod = grep {/v2max/} qx{$model -f$s $env $rate0 d/j$s.$t 2>&1};
+ @mod = grep {/v2max/} qx{$model -f$s -e$env $rate0 d/j$s.$t 2>&1};
} else {
qx{$sox -r$rate0 d/i$s.$t -r$rate1 d/u$s.$t $effect 2>/dev/null};
if ($updown) {
qx{$sox -r$rate1 d/u$s.$t -r$rate0 d/o$s.$t $effect 2>/dev/null};
- @mod = grep {/v2max/} qx{$model -f$s $env $rate0:$rate0 d/o$s.$t 2>&1};
+ @mod = grep {/v2max/} qx{$model -f$s -e$env $rate0:$rate0 d/o$s.$t 2>&1};
}else{
- @mod = grep {/v2max/} qx{$model -f$s $env $rate0:$rate1 d/u$s.$t 2>&1};
+ @mod = grep {/v2max/} qx{$model -f$s -e$env $rate0:$rate1 d/u$s.$t 2>&1};
}
}
print STDERR "$s: ",@mod;
--- a/test/wtest.pl
+++ b/test/wtest.pl
@@ -28,7 +28,7 @@
my $rate=8000; # sample rates
my $p=200; # silence before/after tonepulse
-my $env="-e2000:8000:2000"; # attack, duration, drop
+my $env="-e400:800:400"; # attack, duration, drop
my ($ding,$model,$t,$rms,$lim)=("./ding","./model","sw",11585.2, 0.5);
@@ -78,9 +78,11 @@
qx{$toast -l d/i$s.$t};
qx{$toast -dl d/i$s.$t.gsm};
}else{
+ qx{cp d/i$s.$t d/a$s.$t 2>/dev/null};
qx{$sox -r$rate d/i$s.$t -g d/g$s.wav $effect 2>/dev/null};
unlink "d/i$s.$t";
qx{$sox d/g$s.wav d/i$s.$t 2>/dev/null};
+ qx{cp d/i$s.$t d/b$s.$t 2>/dev/null};
unlink "d/g$s.wav";
}