ref: c7dbcf529c434f00da0d25fc7daba11a01141acb
parent: 00071341d288c17fd063d92b29cbe45f0feff564
author: rrt <rrt>
date: Mon Nov 13 19:57:29 EST 2006
Add [email protected]'s bass/treble filters patch, which also adds visualisation of filters' frequency response via Octave, improves the self-tests, and allows .au files' number of channels and rates to be overridden on the command-line, as for WAV files.
--- a/Changelog
+++ b/Changelog
@@ -20,6 +20,12 @@
o Add FLAC support ([email protected])
o Allow encoding quality to be specified (works for Ogg too, but not
MP3).
+ o bass and treble altering effects. ([email protected])
+ o Visualisation of various filters' frequency response via Octave.
+ ([email protected])
+ o Allow the rate and number of channels of .au files to be overridden
+ by command-line arguments. ([email protected])
+ o More and better self-tests. ([email protected])
sox-12.18.2
-----------
--- a/README
+++ b/README
@@ -1,11 +1,12 @@
SoX: Sound eXchange
-------------------
-SoX (also known as Sound eXchange) translates sound files between different
-file formats, and optionally applies various sound effects.
+SoX (also known as Sound eXchange) translates sound files between
+different file formats, and optionally applies various sound effects.
-SoX is intended as the Swiss Army knife of sound processing tools. It
-doesn't do anything very well, but sooner or later it comes in very handy.
+SoX is intended as the Swiss Army knife of sound processing tools. It
+doesn't do anything very well, but sooner or later it comes in very
+handy.
This release understands:
@@ -25,7 +26,6 @@
o Macintosh HCOM files
o Amiga MAUD files
o MP3 files (with optional external library)
- 0 Psion Record.app files
o IRCAM SoundFile files
o NIST SPHERE files
o Turtle beach SampleVision files.
@@ -33,6 +33,7 @@
o Yamaha TX-16W sampler files.
o Sound Blaster .VOC files
o Ogg Vorbis files (with optional external library)
+ o FLAC files (with optional external library)
o Dialogic/OKI ADPCM files (.VOX)
o Microsoft .WAV files
o PCM, u-law, A-law
@@ -39,7 +40,7 @@
o MS ADPCM, IMA ADPCM
o GSM
o RIFX (big endian)
- o Psion (palmtop) A-law WVE files
+ o Psion (palmtop) A-law WVE files and Record voice notes
o Pseudo-file formats that allow direct playing/recording
from some audio devices under UNIX.
o Pseudo-nul file that reads and writes from/to nowhere
@@ -49,11 +50,13 @@
o Channel averaging, duplication, and removal (general mixer)
o Band-pass filters
o Band-reject filter
+ o Bass tone control
o Compress and Expand (compand) the dynamic range of a sample.
o Chorus effect
o DCShift audio. Useful to get the best volume adjustments.
o Deemphases filter
- o Move sound stage of CD audio to in front of you (for headphone use)
+ o Move sound stage of CD audio to in front of you (for headphone
+ use)
o Add an echo
o Add a sequence of echos
o Fade in and out
@@ -71,23 +74,28 @@
changes using real signal theory!
o Apply a reverb effect
o Reverse the sound samples (to search for Satanic messages ;-)
- o Detect periods of silence and start and stop processing based on it
- o Change the speed of samples being played (like speeding up the motor
- on a tape recorder)
+ o Detect periods of silence and start and stop processing based on
+ it
+ o Change the speed of samples being played (like speeding up the
+ motor on a tape recorder)
o Display general stats on a sound sample
- o Stretch/shorten the duration of a sound file (without affecting pitch).
+ o Stretch/shorten the duration of a sound file (without affecting
+ pitch).
o Swap stereo channels
o Create sounds with a simple synthesizer.
+ o Treble tone control
o Trim audio data from beginning and end of file.
o Add the world-famous Fender Vibro-Champ effect
o Adjust volume of samples
o Noise elimination using frequency profiling
+ o Resample using libsamplerate (aka Secret Rabbit code, optional
+ external library).
Installing:
-Unless your using a pre-compiled binary version, you will need to compile
-SoX as described in the INSTALL file. Please read that file for further
-instructions.
+Unless your using a pre-compiled binary version, you will need to
+compile SoX as described in the INSTALL file. Please read that file
+for further instructions.
SoX is distributed with two text files named sox.txt and soxexam.txt.
These files give a background on how SoX deals with sound files and
@@ -94,20 +102,20 @@
what command line options are available to convert a sound file to
another file format and how to apply sound effects.
-SoX has an auto-detect feature that attempts to figure out
-the nature of a sound file. It does this by looking for 'magic values'
-in the header of the audio file. If it is unable to detect the format
-of the sound file then the user must use command line options to
-inform SoX.
+SoX has an auto-detect feature that attempts to figure out the nature
+of a sound file. It does this by looking for 'magic values' in the
+header of the audio file. If it is unable to detect the format of the
+sound file then the user must use command line options to inform SoX.
I hope to inspire the creation of a common base of sound processing
-tools for computer multimedia work, similar to the PBM toolkit for
+tools for computer multimedia work, similar to the PBM toolkit for
image manipulation.
-If you have bug fixes/enhancements, please send it to me as I would like
-to coordinate the releases. Please document your changes. I do not
-possess every kind of computer currently sold, and SoX is now beyond
-the phase where I can understand and test most of your contributions.
+If you have bug fixes/enhancements, please send it to me as I would
+like to coordinate the releases. Please document your changes. I do
+not possess every kind of computer currently sold, and SoX is now
+beyond the phase where I can understand and test most of your
+contributions.
-The majority of SoX features and source code are contributed
-by you the user. Thank you very much for making SoX a success!
+The majority of SoX features and source code are contributed by you
+the user. Thank you very much for making SoX a success!
--- a/sox.1
+++ b/sox.1
@@ -125,6 +125,18 @@
Prints usage information on the specified effect. The name
\fBall\fR can be used to disable usage on all effects.
.TP 10
+\fB-o\fR
+Run in a mode that can be used, in conjunction with the GNU
+Octave program, to assist with the selection and configuration
+of many of the filtering effects. For the first given effect
+that supports the \fI-o\fR option, SoX will output Octave
+commands to plot the effect's transfer function, and then exit
+without actually processing any audio. E.g.
+
+ sox -o input-file -e highpass 1320 > plot.m
+.br
+ octave plot.m
+.TP 10
\fB-p\fR
Run in preview mode and run fast. This will somewhat speed up
SoX when the output format has a different number of channels and
@@ -322,6 +334,15 @@
These can be dealt with using the
.B .ul
format (see below).
+.br
+ It is possible to override .au file header information
+with the
+.B -r
+and
+.B -c
+options, in which case
+.I SoX
+will issue a warning to that effect.
.TP 10
.B .avr
Audio Visual Research.
@@ -705,12 +726,56 @@
.I center
frequency and settling around it.
See \fBfilter\fR for a bandpass effect with steeper shoulders.
+
+This effect supports the \fI-o\fR option (see above).
+
.TP 10
bandpass \fIfrequency bandwidth\fB
Butterworth bandpass filter. Description coming soon!
+
+This effect supports the \fI-o\fR option (see above).
+
.TP 10
bandreject \fIfrequency bandwidth\fB
Butterworth bandreject filter. Description coming soon!
+
+This effect supports the \fI-o\fR option (see above).
+
+.TP 10
+bass|treble \fIgain\fR [\fIfrequency\fR] [\fIslope\fR]
+Boost or cut the bass (lower) or treble (upper) frequencies of
+the audio signal using a two-pole shelving filter with (by
+default) a response similar to that of a standard hi-fi's
+(Baxandall) tone controls.
+
+\fIgain\fR is a negative or positive number that specifies the
+dB gain at 0Hz (for \fIbass\fR), or whichever is the lower of
+~22kHz and the Nyquist frequency (for \fItreble\fR). Its useful
+range is about -20.0 (for a large cut) to +20.0 (for a large
+boost).
+.br
+ N.B. When using a positive \fIgain\fR, in order to prevent
+clipping, it may be necessary to precede this effect with a
+suitable attenuation using the \fI-v\fR option or the \fIvol\fR
+effect. SoX will display a warning message should clipping
+occur.
+
+If desired, the filter can be fine-tuned using the following
+optional parameters (in either order):
+
+\fIfrequency\fR sets the filter's centre frequency and so can be
+used to extend or reduce the frequency range to be boosted or
+cut. The default value is 100Hz (for \fIbass\fR) or 3kHz (for
+\fItreble\fR).
+
+\fIslope\fR is a number between 0 and 1.0 that determines how
+steep the filter's shelf transition is. Its useful range is
+about 0.3 (for a gentle slope) to 1.0 (for a steep slope). The
+default value is 0.5.
+
+The \fIbass\fR and \fItreble\fR effects support the \fI-o\fR
+option (see above).
+
.TP
chorus \fIgain-in gain-out delay decay speed depth
.TP 10
@@ -780,6 +845,9 @@
audio CD format. The frequency response of pre-emphasized
recordings is rectified. The filtering is defined in the
standard document ISO 908.
+
+This effect supports the \fI-o\fR option (see above).
+
.TP 10
earwax
Makes sound easier to listen to on headphones.
@@ -856,9 +924,15 @@
in the middle of the drop.
The slope of the filter is quite gentle.
See \fBfilter\fR for a highpass effect with sharper cutoff.
+
+This effect supports the \fI-o\fR option (see above).
+
.TP 10
highpass \fIfrequency\fB
Butterworth highpass filter. Description coming soon!
+
+This effect supports the \fI-o\fR option (see above).
+
.TP 10
lowp \fIfrequency\fR
Apply a single pole recursive low-pass filter.
@@ -867,9 +941,15 @@
in the middle of the drop.
The slope of the filter is quite gentle.
See \fBfilter\fR for a lowpass effect with sharper cutoff.
+
+This effect supports the \fI-o\fR option (see above).
+
.TP 10
lowpass \fIfrequency\fB
Butterworth lowpass filter. Description coming soon!
+
+This effect supports the \fI-o\fR option (see above).
+
.TP 10
mask
Add "masking noise" to signal.
@@ -1295,6 +1375,10 @@
\fIp2\fR trapezium: ON time (0..100)
\fIp3\fR trapezium: falling slope position (0..100)
+.TP 10
+treble \fIgain\fR [\fIfrequency\fR] [\fIslope\fR]
+See the description of the \fIbass\fR effect for details.
+
.TP 10
trim \fIstart\fR [ \fIlength\fR ]
Trim can trim off unwanted audio data from the beginning and end of the
--- a/src/Makefile.dos
+++ b/src/Makefile.dos
@@ -22,6 +22,7 @@
EOBJ = avg.obj band.obj bandpass.obj breject.obj btrworth.obj chorus.obj \
compand.obj copy.obj dcshift.obj deemphas.obj earwax.o \
echo.obj echos.obj fade.obj FFT.obj filter.obj flanger.obj \
+ biquad.obj tone.obj \
highp.obj highpass.obj lowp.obj lowpass.obj mask.obj mcompand.obj \
noiseprof.obj noisered.obj phaser.obj pitch.obj pan.obj \
polyphase.obj rate.obj repeat.obj resample.obj \
--- a/src/Makefile.gcc
+++ b/src/Makefile.gcc
@@ -27,6 +27,7 @@
EOBJ = avg.o band.o bandpass.o breject.o btrworth.o chorus.o compand.o \
copy.o dcshift.o deemphas.o earwax.o echo.o echos.o fade.o FFT.o \
+ biquad.o tone.o \
filter.o flanger.o highp.o highpass.o lowp.o lowpass.o \
mask.o mcompand.o noiseprof.o noisered.o pan.o phaser.o pitch.o \
polyphas.o rate.o repeat.o resample.o reverb.o reverse.o \
--- a/src/Makefile.in
+++ b/src/Makefile.in
@@ -49,6 +49,7 @@
EOBJ = avg.o band.o bandpass.o breject.o btrworth.o chorus.o compand.o \
copy.o dcshift.o deemphas.o earwax.o echo.o echos.o \
+ biquad.o tone.o \
fade.o FFT.o filter.o flanger.o highp.o highpass.o lowp.o \
lowpass.o mask.o mcompand.o noiseprof.o noisered.o pan.o \
phaser.o pitch.o polyphas.o rabbit.o rate.o repeat.o resample.o \
--- a/src/au.c
+++ b/src/au.c
@@ -233,13 +233,21 @@
break;
}
+
/* Read the sampling rate */
st_readdw(ft, &sample_rate);
- ft->info.rate = sample_rate;
+ if (ft->info.rate == 0 || ft->info.rate == sample_rate)
+ ft->info.rate = sample_rate;
+ else
+ st_report("User options overriding rate read in .au header");
/* Read the number of channels */
st_readdw(ft, &channels);
- ft->info.channels = (int) channels;
+ if (ft->info.channels == -1 || ft->info.channels == (int) channels)
+ ft->info.channels = (int) channels;
+ else
+ st_report("User options overriding channels read in .au header");
+
/* Skip the info string in header; print it if verbose */
hdr_size -= SUN_HDRSIZE; /* #bytes already read */
--- a/src/band.c
+++ b/src/band.c
@@ -106,6 +106,27 @@
else
band->A = sqrt(1-band->B*band->B/(4*band->C))*(1-band->C);
band->out1 = band->out2 = 0.0;
+ if (effp->globalinfo.octave_plot_effect)
+ {
+ printf(
+ "title('SoX effect: %s centre=%g width=%g (rate=%u)')\n"
+ "xlabel('Frequency (Hz)')\n"
+ "ylabel('Amplitude Response (dB)')\n"
+ "Fs=%u;minF=10;maxF=Fs/2;\n"
+ "axis([minF maxF -75 25])\n"
+ "sweepF=logspace(log10(minF),log10(maxF),200);\n"
+ "grid on\n"
+ "[h,w]=freqz([%f 0 0],[1 %f %f],sweepF,Fs);\n"
+ "semilogx(w,20*log10(h),'b')\n"
+ "pause\n"
+ , effp->name, band->center, band->width
+ , effp->ininfo.rate, effp->ininfo.rate
+ , band->A
+ , band->B
+ , band->C
+ );
+ exit(0);
+ }
return (ST_SUCCESS);
}
--- a/src/bandpass.c
+++ b/src/bandpass.c
@@ -76,6 +76,7 @@
butterworth->b [0] = -c * d * butterworth->a [0];
butterworth->b [1] = (c - 1.0) * butterworth->a[0];
+ st_butterworth_plot(effp);
return (ST_SUCCESS);
}
--- a/src/breject.c
+++ b/src/breject.c
@@ -76,6 +76,7 @@
butterworth->b [0] = butterworth->a[1];
butterworth->b [1] = (1.0 - c) * butterworth->a[0];
+ st_butterworth_plot(effp);
return (ST_SUCCESS);
}
--- a/src/btrworth.c
+++ b/src/btrworth.c
@@ -47,6 +47,35 @@
return (ST_SUCCESS);
}
+void st_butterworth_plot (eff_t effp)
+{
+ butterworth_t butterworth = (butterworth_t) effp->priv;
+
+ if (effp->globalinfo.octave_plot_effect)
+ {
+ printf(
+ "title('SoX effect: %s centre=%g width=%g (rate=%u)')\n"
+ "xlabel('Frequency (Hz)')\n"
+ "ylabel('Amplitude Response (dB)')\n"
+ "Fs=%u;minF=10;maxF=Fs/2;\n"
+ "axis([minF maxF -95 5])\n"
+ "sweepF=logspace(log10(minF),log10(maxF),200);\n"
+ "grid on\n"
+ "[h,w]=freqz([%f %f %f],[1 %f %f],sweepF,Fs);\n"
+ "semilogx(w,20*log10(h),'b')\n"
+ "pause\n"
+ , effp->name, butterworth->frequency, butterworth->bandwidth
+ , effp->ininfo.rate, effp->ininfo.rate
+ , butterworth->a[0]
+ , butterworth->a[1]
+ , butterworth->a[2]
+ , butterworth->b[0]
+ , butterworth->b[1]
+ );
+ exit(0);
+ }
+}
+
int st_butterworth_flow (eff_t effp, st_sample_t *ibuf, st_sample_t *obuf,
st_size_t *isamp, st_size_t *osamp)
{
--- a/src/btrworth.h
+++ b/src/btrworth.h
@@ -32,6 +32,7 @@
*/
int st_butterworth_start (eff_t effp);
+void st_butterworth_plot (eff_t effp);
int st_butterworth_flow (eff_t effp, st_sample_t *ibuf, st_sample_t *obuf,
st_size_t *isamp, st_size_t *osamp);
--- a/src/deemphas.c
+++ b/src/deemphas.c
@@ -130,6 +130,11 @@
return (ST_SUCCESS);
}
+/* filter coefficients */
+#define a1 -0.62786881719628784282
+#define b0 0.45995451989513153057
+#define b1 -0.08782333709141937339
+
/*
* Prepare processing.
* Do all initializations.
@@ -158,6 +163,25 @@
deemph->lastin = 0;
deemph->lastout = 0.0;
}
+ if (effp->globalinfo.octave_plot_effect)
+ {
+ printf(
+ "title('SoX effect: %s (rate=%u)')\n"
+ "xlabel('Frequency (Hz)')\n"
+ "ylabel('Amplitude Response (dB)')\n"
+ "Fs=%u;minF=10;maxF=Fs/2;\n"
+ "axis([minF maxF -25 25])\n"
+ "sweepF=logspace(log10(minF),log10(maxF),200);\n"
+ "grid on\n"
+ "[h,w]=freqz([%f %f],[1 %f],sweepF,Fs);\n"
+ "semilogx(w,20*log10(h),'b')\n"
+ "pause\n"
+ , effp->name
+ , effp->ininfo.rate, effp->ininfo.rate
+ , b0, b1, a1
+ );
+ exit(0);
+ }
return (ST_SUCCESS);
}
@@ -165,11 +189,6 @@
* Processed signed long samples from ibuf to obuf.
* Return number of samples processed.
*/
-
-/* filter coefficients */
-#define a1 -0.62786881719628784282
-#define b0 0.45995451989513153057
-#define b1 -0.08782333709141937339
int st_deemph_flow(eff_t effp, st_sample_t *ibuf, st_sample_t *obuf,
st_size_t *isamp, st_size_t *osamp)
--- a/src/handlers.c
+++ b/src/handlers.c
@@ -84,6 +84,7 @@
st_effect_fn_t st_effect_fns[] = {
st_avg_effect_fn,
st_band_effect_fn,
+ st_bass_effect_fn,
st_bandpass_effect_fn,
st_bandreject_effect_fn,
st_chorus_effect_fn,
@@ -124,6 +125,7 @@
st_stretch_effect_fn,
st_swap_effect_fn,
st_synth_effect_fn,
+ st_treble_effect_fn,
st_trim_effect_fn,
st_vibro_effect_fn,
st_vol_effect_fn,
--- a/src/highp.c
+++ b/src/highp.c
@@ -73,6 +73,26 @@
highp->A1 = (-1 * (1 + highp->B1)) / 2;
highp->inm1 = 0.0;
highp->outm1 = 0.0;
+
+ if (effp->globalinfo.octave_plot_effect)
+ {
+ printf(
+ "title('SoX effect: %s cutoff=%g (rate=%u)')\n"
+ "xlabel('Frequency (Hz)')\n"
+ "ylabel('Amplitude Response (dB)')\n"
+ "Fs=%u;minF=10;maxF=Fs/2;\n"
+ "axis([minF maxF -95 5])\n"
+ "sweepF=logspace(log10(minF),log10(maxF),200);\n"
+ "grid on\n"
+ "[h,w]=freqz([%f %f],[1 %f],sweepF,Fs);\n"
+ "semilogx(w,20*log10(h),'b')\n"
+ "pause\n"
+ , effp->name, highp->cutoff
+ , effp->ininfo.rate, effp->ininfo.rate
+ , highp->A0, highp->A1, -highp->B1
+ );
+ exit(0);
+ }
return (ST_SUCCESS);
}
--- a/src/highpass.c
+++ b/src/highpass.c
@@ -71,6 +71,7 @@
butterworth->b [0] = 2 * (c * c - 1.0) * butterworth->a[0];
butterworth->b [1] = (1.0 - sqrt(2.0) * c + c * c) * butterworth->a [0];
+ st_butterworth_plot(effp);
return (ST_SUCCESS);
}
--- a/src/lowp.c
+++ b/src/lowp.c
@@ -69,6 +69,26 @@
lowp->B = exp((-2.0 * M_PI * (lowp->cutoff / effp->ininfo.rate)));
lowp->A = 1 - lowp->B;
lowp->outm1 = 0.0;
+
+ if (effp->globalinfo.octave_plot_effect)
+ {
+ printf(
+ "title('SoX effect: %s cutoff=%g (rate=%u)')\n"
+ "xlabel('Frequency (Hz)')\n"
+ "ylabel('Amplitude Response (dB)')\n"
+ "Fs=%u;minF=10;maxF=Fs/2;\n"
+ "axis([minF maxF -95 5])\n"
+ "sweepF=logspace(log10(minF),log10(maxF),200);\n"
+ "grid on\n"
+ "[h,w]=freqz([%f 0],[1 %f],sweepF,Fs);\n"
+ "semilogx(w,20*log10(h),'b')\n"
+ "pause\n"
+ , effp->name, lowp->cutoff
+ , effp->ininfo.rate, effp->ininfo.rate
+ , lowp->A, -lowp->B
+ );
+ exit(0);
+ }
return (ST_SUCCESS);
}
--- a/src/lowpass.c
+++ b/src/lowpass.c
@@ -57,6 +57,7 @@
butterworth->b [0] = 2 * (1.0 - c * c) * butterworth->a[0];
butterworth->b [1] = (1.0 - sqrt(2.0) * c + c * c) * butterworth->a [0];
+ st_butterworth_plot(effp);
return (ST_SUCCESS);
}
--- a/src/play.in
+++ b/src/play.in
@@ -93,7 +93,7 @@
# loop over arguments
while [ $# -ne 0 ]; do
case "$1" in
- avg|band|bandpass|bandreject|chorus|compand|copy|cut|deemph|earwax|echo|echos|fade|filter|flanger|highp|highpass|lowp|lowpass|map|mask|mcompand|noiseprof|noisered|pan|phaser|pick|pitch|polyphase|rate|repeat|resample|reverb|reverse|silence|speed|split|stat|stretch|swap|trim|vibro|vol)
+ avg|band|bandpass|bandreject|bass|chorus|compand|copy|cut|deemph|earwax|echo|echos|fade|filter|flanger|highp|highpass|lowp|lowpass|map|mask|mcompand|noiseprof|noisered|pan|phaser|pick|pitch|polyphase|rate|repeat|resample|reverb|reverse|silence|speed|split|stat|stretch|swap|treble|trim|vibro|vol)
effects="$@"
break
;;
--- a/src/sox.c
+++ b/src/sox.c
@@ -69,6 +69,7 @@
static int clipped = 0; /* Volume change clipping errors */
static int writing = 1; /* are we writing to a file? assume yes. */
static int soxpreview = 0; /* preview mode */
+static st_globalinfo_t globalinfo;
static int user_abort = 0;
@@ -285,7 +286,7 @@
return(0);
}
-static char *getoptstr = "+r:v:t:c:C:phsuUAaigbwlfdxVSq";
+static char *getoptstr = "+r:v:t:c:C:phsuUAaigbwlfdxVSqo";
static struct option long_options[] =
{
@@ -318,6 +319,10 @@
/* no return from above */
break;
+ case 'o':
+ globalinfo.octave_plot_effect = true;
+ break;
+
case 'p':
soxpreview++;
break;
@@ -920,6 +925,8 @@
for (i = 0; i < nuser_effects; i++)
{
+ user_efftab[i].globalinfo = globalinfo;
+
if (user_efftab[i].h->flags & ST_EFF_CHAN)
{
haschan++;
--- a/src/st.h
+++ b/src/st.h
@@ -43,7 +43,6 @@
/* Minimum and maximum values a sample can hold. */
#define ST_SAMPLE_MAX 2147483647L
#define ST_SAMPLE_MIN (-ST_SAMPLE_MAX - 1L)
-#define ST_SAMPLE_FLOAT_UNSCALE 2147483647.0
#define ST_SAMPLE_FLOAT_SCALE 2147483648.0
#define ST_UNSIGNED_BYTE_TO_SAMPLE(d) ((st_sample_t)((d) ^ 0x80) << 24)
@@ -52,10 +51,8 @@
#define ST_SIGNED_WORD_TO_SAMPLE(d) ((st_sample_t)(d) << 16)
#define ST_UNSIGNED_DWORD_TO_SAMPLE(d) ((st_sample_t)((d) ^ 0x80000000L))
#define ST_SIGNED_DWORD_TO_SAMPLE(d) ((st_sample_t)d)
-/* FIXME: This is an approximation because it
- * doesn't account for -1.0 mapping to -FLOAT_SCALE-1. */
-#define ST_FLOAT_DWORD_TO_SAMPLE(d) ((st_sample_t)(d*ST_SAMPLE_FLOAT_UNSCALE))
-#define ST_FLOAT_DDWORD_TO_SAMPLE(d) ((st_sample_t)(d*ST_SAMPLE_FLOAT_UNSCALE))
+#define ST_FLOAT_DWORD_TO_SAMPLE(d) (d==1? ST_SAMPLE_MAX : (st_sample_t)(d*ST_SAMPLE_FLOAT_SCALE))
+#define ST_FLOAT_DDWORD_TO_SAMPLE ST_FLOAT_DWORD_TO_SAMPLE
#define ST_SAMPLE_TO_UNSIGNED_BYTE(d) ((uint8_t)((d) >> 24) ^ 0x80)
#define ST_SAMPLE_TO_SIGNED_BYTE(d) ((int8_t)((d) >> 24))
#define ST_SAMPLE_TO_UNSIGNED_WORD(d) ((uint16_t)((d) >> 16) ^ 0x8000)
@@ -90,6 +87,13 @@
{ samp = ST_SAMPLE_MIN; clips++; } \
} while (0)
+/* Rvalue MACRO to round and clip a double to a st_sample_t,
+ * and increment a counter if clipping occurs.
+ */
+#define ST_ROUND_CLIP_COUNT(d, clips) \
+ (d < 0? d <= ST_SAMPLE_MIN - 0.5? ++clips, ST_SAMPLE_MIN: d - 0.5 \
+ : d >= ST_SAMPLE_MAX + 0.5? ++clips, ST_SAMPLE_MAX: d + 0.5)
+
/* MACRO to clip a normalized floating point data between 1.0 and -1.0
* to those limits and increment a counter when clipping occurs.
*/
@@ -108,6 +112,13 @@
#define ST_SSIZE_MAX 0x7fffffffL
#define ST_SSIZE_MIN (-ST_SSIZE_MAX - 1L)
+/* Global parameters */
+
+typedef struct st_globalinfo
+{
+ bool octave_plot_effect;/* to help user choose effect & options */
+} st_globalinfo_t;
+
/* Signal parameters */
typedef struct st_signalinfo
@@ -285,6 +296,7 @@
struct st_effect
{
char *name; /* effect name */
+ struct st_globalinfo globalinfo;/* global ST parameters */
struct st_signalinfo ininfo; /* input signal specifications */
struct st_signalinfo outinfo; /* output signal specifications */
const st_effect_t *h; /* effects driver */
--- a/src/st_i.h
+++ b/src/st_i.h
@@ -234,6 +234,7 @@
extern const st_effect_t *st_avg_effect_fn(void);
extern const st_effect_t *st_pick_effect_fn(void);
extern const st_effect_t *st_band_effect_fn(void);
+extern const st_effect_t *st_bass_effect_fn(void);
extern const st_effect_t *st_bandpass_effect_fn(void);
extern const st_effect_t *st_bandreject_effect_fn(void);
extern const st_effect_t *st_chorus_effect_fn(void);
@@ -273,6 +274,7 @@
extern const st_effect_t *st_stretch_effect_fn(void);
extern const st_effect_t *st_swap_effect_fn(void);
extern const st_effect_t *st_synth_effect_fn(void);
+extern const st_effect_t *st_treble_effect_fn(void);
extern const st_effect_t *st_trim_effect_fn(void);
extern const st_effect_t *st_vibro_effect_fn(void);
extern const st_effect_t *st_vol_effect_fn(void);
--- a/src/tests.sh
+++ b/src/tests.sh
@@ -1,219 +1,57 @@
#!/bin/sh
#
-# SOX Test script.
+# SOX Regression Test script.
#
-# This script is just a quick sanity check of SOX on lossless conversions.
+# This script is just a quick sanity check of SOX on lossless format conversions.
# verbose options
-#noise=-V
+#verbose=-V
-./sox $noise monkey.au raw1.ub
+getFormat () {
+ formatText=$1; formatFlags=""
+ case $1 in
+ al ) formatText="alaw byte" ;;
+ sb ) formatText="signed byte" ;;
+ sl ) formatText="signed long" ;;
+ sw ) formatText="signed word" ;;
+ ul ) formatText="ulaw byte" ;;
+ ub ) formatText="unsigned byte" ;;
+ uw ) formatText="unsigned word" ;;
+ raw) formatText="float"; formatFlags="-f -l" ;;
+ au ) formatFlags="-s -b" ;;
+ wav) formatFlags="-u -b" ;;
+ esac
+}
+
+convertToAndFrom () {
+ while [ $# != 0 ]; do
+ getFormat $format1; format1Text=$formatText; format1Flags=$formatFlags
+ getFormat $1; format2Text=$formatText; format2Flags=$formatFlags
+ ./sox $verbose -r $rate monkey.au $format1Flags input.$format1
+ ./sox $verbose -r $rate -c 1 $format1Flags input.$format1 $format2Flags intermediate.$1
+ ./sox $verbose -r $rate -c 1 $format2Flags intermediate.$1 $format1Flags output.$format1
+ if cmp -s input.$format1 output.$format1
+ then
+ echo "ok convert \"$format1Text\" <--> \"$format2Text\"."
+ else
+ echo "*FAIL* convert \"$format1Text\" <--> \"$format2Text\"."
+ exit 1 # This allows failure inspection.
+ fi
+ rm -f input.$format1 intermediate.$1 output.$format1
+ shift
+ done
+}
-# Convert between unsigned bytes and signed bytes
-./sox $noise -r 8012 -c 1 raw1.ub raw1.sb
-./sox $noise -r 8012 -c 1 raw1.sb raw2.ub
-if cmp -s raw1.ub raw2.ub
-then
- echo "Conversion between unsigned bytes and signed bytes was successful"
-else
- echo "Error converting between signed and unsigned bytes"
-fi
-rm -f raw1.sb raw2.ub
+format1=ub
+rate=8012
+convertToAndFrom sb sw sl al uw raw
-./sox $noise -r 8012 -c 1 raw1.ub raw1.sw
-./sox $noise -r 8012 -c 1 raw1.sw raw2.ub
-if cmp -s raw1.ub raw2.ub
-then
- echo "Conversion between unsigned bytes and signed words was successful"
-else
- echo "Error converting between signed words and unsigned bytes"
-fi
-rm -f raw1.sw raw2.ub
+format1=sw
+convertToAndFrom sl ul uw raw
-./sox $noise -r 8012 -c 1 raw1.ub raw1.al
-./sox $noise -r 8012 -c 1 raw1.al raw2.ub
-if cmp -s raw1.ub raw2.ub
-then
- echo "Conversion between unsigned bytes and alaw bytes was successful"
-else
- echo "Error converting between alaw and unsigned bytes"
-fi
-rm -f raw1.al raw2.ub
-
-
-./sox $noise -r 8012 -c 1 raw1.ub raw1.uw
-./sox $noise -r 8012 -c 1 raw1.uw raw2.ub
-if cmp -s raw1.ub raw2.ub
-then
- echo "Conversion between unsigned bytes and unsigned words was successful"
-else
- echo "Error converting between unsigned words and unsigned bytes"
-fi
-rm -f raw1.uw raw2.ub
-
-./sox $noise -r 8012 -c 1 raw1.ub raw1.sl
-./sox $noise -r 8012 -c 1 raw1.sl raw2.ub
-if cmp -s raw1.ub raw2.ub
-then
- echo "Conversion between unsigned bytes and signed long was successful"
-else
- echo "Error converting between signed long and unsigned bytes"
-fi
-rm -f raw1.sl raw2.ub
-
-./sox $noise -r 8012 -c 1 raw1.ub -f -l raw1.raw
-./sox $noise -r 8012 -c 1 -f -l raw1.raw raw2.ub
-if cmp -s raw1.ub raw2.ub
-then
- echo "Conversion between unsigned bytes and float was successful"
-else
- echo "Error converting between float and unsigned bytes"
-fi
-rm -f raw1.raw raw2.ub
-
-rm -f raw1.ub
-./sox $noise monkey.au raw1.sw
-
-./sox $noise -r 8012 -c 1 raw1.sw raw1.ul
-./sox $noise -r 8012 -c 1 raw1.ul raw2.sw
-if cmp -s raw1.sw raw2.sw
-then
- echo "Conversion between signed words and ulaw bytes was successful"
-else
- echo "Error converting between ulaw and signed words"
-fi
-rm -f raw1.ul raw2.sw
-
-rm -f raw1.sw
-
-./sox $noise monkey.au -u -b monkey1.wav
-
-echo ""
-
-ext=8svx
-./sox $noise monkey1.wav convert.$ext
-./sox $noise convert.$ext -u -b monkey2.wav
-if cmp -s monkey1.wav monkey2.wav
-then
- echo "Conversion between wav and $ext was successful"
-else
- echo "Error converting between wav and $ext."
-fi
-rm -f convert.$ext monkey2.wav
-
-ext=aiff
-./sox $noise monkey1.wav convert.$ext
-./sox $noise convert.$ext -u -b monkey2.wav
-if cmp -s monkey1.wav monkey2.wav
-then
- echo "Conversion between wav and $ext was successful"
-else
- echo "Error converting between wav and $ext."
-fi
-rm -f convert.$ext monkey2.wav
-
-# AU doesn't support unsigned so use signed
-ext=au
-./sox $noise monkey1.wav -s -b convert.$ext
-./sox $noise convert.$ext -u -b monkey2.wav
-if cmp -s monkey1.wav monkey2.wav
-then
- echo "Conversion between wav and $ext was successful"
-else
- echo "Error converting between wav and $ext."
-fi
-rm -f convert.$ext monkey2.wav
-
-ext=avr
-./sox $noise monkey1.wav convert.$ext
-./sox $noise convert.$ext -u -b monkey2.wav
-if cmp -s monkey1.wav monkey2.wav
-then
- echo "Conversion between wav and $ext was successful"
-else
- echo "Error converting between wav and $ext."
-fi
-rm -f convert.$ext monkey2.wav
-
-ext=dat
-./sox $noise monkey1.wav convert.$ext
-./sox $noise convert.$ext -u -b monkey2.wav
-if cmp -s monkey1.wav monkey2.wav
-then
- echo "Conversion between wav and $ext was successful"
-else
- echo "Error converting between wav and $ext."
-fi
-rm -f convert.$ext monkey2.wav
-
-ext=hcom
-# HCOM has to be at specific sample rate.
-./sox $noise -r 5512 monkey1.wav nmonkey1.wav
-./sox $noise nmonkey1.wav convert.$ext
-./sox $noise convert.$ext -u -b monkey2.wav
-if cmp -s nmonkey1.wav monkey2.wav
-then
- echo "Conversion between wav and $ext was successful"
-else
- echo "Error converting between wav and $ext."
-fi
-rm -f convert.$ext nmonkey1.wav monkey2.wav
-
-ext=maud
-./sox $noise monkey1.wav convert.$ext
-./sox $noise convert.$ext -u -b monkey2.wav
-if cmp -s monkey1.wav monkey2.wav
-then
- echo "Conversion between wav and $ext was successful"
-else
- echo "Error converting between wav and $ext."
-fi
-rm -f convert.$ext monkey2.wav
-
-ext=sf
-./sox $noise monkey1.wav convert.$ext
-./sox $noise convert.$ext -u -b monkey2.wav
-if cmp -s monkey1.wav monkey2.wav
-then
- echo "Conversion between wav and $ext was successful"
-else
- echo "Error converting between wav and $ext."
-fi
-rm -f convert.$ext monkey2.wav
-
-ext=smp
-./sox $noise monkey1.wav convert.$ext
-./sox $noise convert.$ext -u -b monkey2.wav
-if cmp -s monkey1.wav monkey2.wav
-then
- echo "Conversion between wav and $ext was successful"
-else
- echo "Error converting between wav and $ext."
-fi
-rm -f convert.$ext monkey2.wav
-
-ext=voc
-./sox $noise -r 8000 monkey1.wav nmonkey1.wav
-./sox $noise nmonkey1.wav convert.$ext
-./sox $noise convert.$ext -u -b monkey2.wav
-if cmp -s nmonkey1.wav monkey2.wav
-then
- echo "Conversion between wav and $ext was successful"
-else
- echo "Error converting between wav and $ext."
-fi
-rm -f convert.$ext nmonkey1.wav monkey2.wav
-
-ext=wve
-./sox $noise -r 8000 monkey1.wav nmonkey1.wav
-./sox $noise nmonkey1.wav convert.$ext
-./sox $noise convert.$ext -u -b monkey2.wav
-if cmp -s nmonkey1.wav monkey2.wav
-then
- echo "Conversion between wav and $ext was successful"
-else
- echo "Error converting between wav and $ext."
-fi
-rm -f convert.$ext nmonkey1.wav monkey2.wav
-
-exit
+format1=wav
+convertToAndFrom 8svx aiff au avr dat maud sf smp
+rate=5512
+convertToAndFrom hcom
+rate=8000
+convertToAndFrom voc wve
--- a/watcom/makefile
+++ b/watcom/makefile
@@ -23,6 +23,7 @@
EOBJ = avg.obj band.obj bandpass.obj breject.obj btrworth.obj chorus.obj &
compand.obj copy.obj dcshift.obj deemphas.obj earwax.obj echo.obj echos.obj &
+biquad.obj tone.obj &
fade.obj FFT.obj filter.obj flanger.obj highp.obj highpass.obj lowp.obj &
lowpass.obj mask.obj mcompand.obj noiseprof.obj noisered.obj phaser.obj &
pitch.obj pan.obj polyphas.obj rate.obj repeat.obj resample.obj reverb.obj &
--- a/win32/stlib.dsp
+++ b/win32/stlib.dsp
@@ -197,6 +197,14 @@
# End Source File
# Begin Source File
+SOURCE=..\src\biquad.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\tone.c
+# End Source File
+# Begin Source File
+
SOURCE=..\src\g711.c
# End Source File
# Begin Source File