ref: 51d22893437c3dcd74d31093e4b0f20d717007b6
parent: af7e8d1b71257abdfc1caf93cce47946a11b606c
author: robs <robs>
date: Wed Dec 6 14:04:36 EST 2006
Improved the accuracy of integer and floating point PCM conversions.
--- a/ChangeLog
+++ b/ChangeLog
@@ -40,7 +40,7 @@
o Fix wav file handler discarding the last PCM sample in certain
circumstances. (robs)
o Add support for 24-bit PCM raw, wav (WAVE_FORMAT_EXTENSIBLE) [FR# 801015],
- aiff, & flac files. (robs)
+ au, aiff, & flac files. (robs)
o Added alias -1 (for -b), -2 (for -w), -4 (for -l), -8 (for -d). (robs)
o Remove old, optional rate change and alaw/ulaw conversion code.
(Reuben Thomas)
@@ -59,6 +59,8 @@
o Documented the butterworth filter effects. (robs)
o Added command line options for specifying the output file
comment. (robs)
+ o Improved the accuracy of integer and floating point PCM
+ conversions. (robs)
sox-12.18.2
-----------
--- a/TODO
+++ b/TODO
@@ -83,11 +83,6 @@
of detecting uint64_t... Use that when possible to speed up
math (won't have to convert back and forth from int to float).
- o Fix conversions to and from st_sample_t to floats. Currently,
- its an approximation because it doesn't account from negative
- side having 1 more value then positive side. That means instead
- of -1:1 range, its more like -0.999:1 or -1:0.9999.
-
o WAV handler is not using world alignment for at least the
main data chunk (expect for GSM).
--- a/sox.1
+++ b/sox.1
@@ -53,6 +53,8 @@
.P
Exit status is 0 for no error, 1 if there is a problem with the command-line arguments, and 2 if an error occurs during file processing.
.P
+\fBFile Format Types\fR
+.br
There are two types of audio file format that
.I SoX
can work with. The first is "self-describing". Such formats
@@ -59,7 +61,8 @@
include a header that completely describe the characteristics of
the audio data that follows.
The header may also allow the inclusion of textual "comments" that can
-be used to describe the audio in some way.
+be used to describe the audio in some way, e.g. for music, the title,
+the author, etc.
.P
The second type is header-less data, often called raw data.
For this type, a
@@ -82,12 +85,62 @@
What encoding the data type uses. Examples are u-law, ADPCM, or signed linear data.
.TP 10
channels
-How many channels are contained in the audio data. Mono (1) and stereo (2) are the two most common.
+The number of audio channels contained in the file. 1 ("mono") and 2
+("stereo") are widely used.
.P
Please refer to the
.B soxexam(1)
manual page for a long description with examples on how to use SoX with
various file formats.
+.P
+\fBFormat Conversion\fR
+.br
+Converting an audio file from one format to another with
+.I SoX
+is "lossless"
+(i.e. converting back again would yield an exact copy of the original
+audio signal)
+where it
+can be, i.e. when not using "lossy" compression (e.g. A-law, mp3, etc.)
+and the number of bits used in the destination format is not less than
+in the source format.
+
+E.g. converting from an 8-bit PCM format to a 16-bit PCM format is
+lossless but converting from a 24-bit PCM format to a 16-bit PCM format isn't.
+When performing a lossy conversion,
+.I SoX
+uses rounding to retain as much accuracy as possible in the
+audio signal.
+.P
+\fBClipping\fR
+.br
+Clipping is distortion that occurs when an audio signal
+level exceeds the range of the chosen representation.
+Clipping is rarely desirable and so should usually be corrected by
+adjusting the audio volume prior to the point at which clipping occurs.
+
+In \fISoX\fR, clipping could occur, as you might expect, when using the
+.I vol
+effect to increase the audio volume, but could also occur with many
+other effects, when converting one format to another, and even when
+simply playing the audio.
+
+Playing an audio file often involves reampling, and processing by
+analogue components that can introduce a small DC offset and/or
+amplification, all of which can produce distortion if the audio signal
+level was intially too close to the clipping point.
+
+For these reasons, it is usual to make sure that a digital audio
+file's signal level does not exceed around 70% of the maximum (linear)
+range available, as this will avoid the majority of clipping problems.
+\fISoX\fR's
+.I stat
+effect can assist here by displaying the signal level in an audio file.
+
+If clipping occurrs at any point during processing, then
+.I SoX
+will display a warning message to that effect.
+
.SH OPTIONS
The option syntax is somewhat complex, but in essence:
.P
@@ -1464,7 +1517,7 @@
Multiple channels can be synthesised by specifying the set of
parameters shown between braces ({}) multiple times;
-the following puts the swept tone in the left channel and "brown"
+the following puts the swept tone in the left channel and adds "brown"
noise in the right:
sox -n output.au synth 3 sine 300-3300 brownnoise
--- a/src/8svx.c
+++ b/src/8svx.c
@@ -300,7 +300,7 @@
while(done < len) {
for (i = 0; i < ft->info.channels; i++) {
- datum = ST_SAMPLE_TO_SIGNED_BYTE(*buf++);
+ datum = ST_SAMPLE_TO_SIGNED_BYTE(*buf++, ft->clippedCount);
/* FIXME: Needs to pass ft struct and not FILE */
putc(datum, p->ch[i]);
}
--- a/src/au.c
+++ b/src/au.c
@@ -80,6 +80,10 @@
*encoding = ST_ENCODING_SIGN2;
*size = ST_SIZE_WORD;
break;
+ case SUN_LIN_24:
+ *encoding = ST_ENCODING_SIGN2;
+ *size = ST_SIZE_24BIT;
+ break;
case SUN_G721:
*encoding = ST_ENCODING_SIGN2;
*size = ST_SIZE_WORD;
@@ -402,6 +406,8 @@
sun_encoding = SUN_LIN_8;
else if (encoding == ST_ENCODING_SIGN2 && size == ST_SIZE_WORD)
sun_encoding = SUN_LIN_16;
+ else if (encoding == ST_ENCODING_SIGN2 && size == ST_SIZE_24BIT)
+ sun_encoding = SUN_LIN_24;
else if (encoding == ST_ENCODING_FLOAT && size == ST_SIZE_32BIT)
sun_encoding = SUN_FLOAT;
else
@@ -421,7 +427,7 @@
if ((encoding = st_ausunencoding(ft->info.size, ft->info.encoding)) == -1) {
st_report("Unsupported output encoding/size for Sun/NeXT header or .AU format not specified.");
- st_report("Only U-law, A-law signed bytes, and signed words are supported.");
+ st_report("Only U-law, A-law, and signed bytes/words/tri-bytes are supported.");
st_report("Defaulting to 8khz u-law");
encoding = SUN_ULAW;
ft->info.encoding = ST_ENCODING_ULAW;
--- a/src/avg.c
+++ b/src/avg.c
@@ -527,7 +527,7 @@
samp = 0.0;
for (i = 0; i < ichan; i++)
samp += ibuf[i] * avg->sources[i][j];
- ST_EFF_SAMPLE_CLIP_COUNT(samp);
+ ST_SAMPLE_CLIP_COUNT(samp, effp->clippedCount);
obuf[j] = samp;
}
}
--- a/src/biquad.c
+++ b/src/biquad.c
@@ -14,7 +14,7 @@
double o0 = *ibuf*p->b0 +p->i1*p->b1 +p->i2*p->b2 -p->o1*p->a1 -p->o2*p->a2;
p->i2 = p->i1, p->i1 = *ibuf++;
p->o2 = p->o1, p->o1 = o0;
- *obuf++ = ST_EFF_ROUND_CLIP_COUNT(o0);
+ *obuf++ = ST_ROUND_CLIP_COUNT(o0, effp->clippedCount);
}
return ST_SUCCESS;
}
--- a/src/btrworth.c
+++ b/src/btrworth.c
@@ -103,7 +103,7 @@
butterworth->y [1] = butterworth->y [0];
butterworth->y [0] = out;
- ST_EFF_SAMPLE_CLIP_COUNT(out);
+ ST_SAMPLE_CLIP_COUNT(out, effp->clippedCount);
*obuf++ = out;
}
--- a/src/chorus.c
+++ b/src/chorus.c
@@ -276,7 +276,7 @@
chorus->maxsamples] * chorus->decay[i];
/* Adjust the output volume and size to 24 bit */
d_out = d_out * chorus->out_gain;
- out = ST_EFF_24BIT_CLIP_COUNT((st_sample_t) d_out);
+ out = ST_24BIT_CLIP_COUNT((st_sample_t) d_out, effp->clippedCount);
*obuf++ = out * 256;
/* Mix decay of delay and input */
chorus->chorusbuf[chorus->counter] = d_in;
@@ -313,7 +313,7 @@
chorus->maxsamples] * chorus->decay[i];
/* Adjust the output volume and size to 24 bit */
d_out = d_out * chorus->out_gain;
- out = ST_EFF_24BIT_CLIP_COUNT((st_sample_t) d_out);
+ out = ST_24BIT_CLIP_COUNT((st_sample_t) d_out, effp->clippedCount);
*obuf++ = out * 256;
/* Mix decay of delay and input */
chorus->chorusbuf[chorus->counter] = d_in;
--- a/src/compand.c
+++ b/src/compand.c
@@ -316,7 +316,7 @@
if (l->delay_buf_size <= 0)
{
checkbuf = ibuf[chan]*(outv/v)*l->outgain;
- ST_EFF_SAMPLE_CLIP_COUNT(checkbuf);
+ ST_SAMPLE_CLIP_COUNT(checkbuf, effp->clippedCount);
obuf[odone] = checkbuf;
idone++;
@@ -328,7 +328,7 @@
{
l->delay_buf_full=1; //delay buffer is now definetly full
checkbuf = l->delay_buf[l->delay_buf_ptr]*(outv/v)*l->outgain;
- ST_EFF_SAMPLE_CLIP_COUNT(checkbuf);
+ ST_SAMPLE_CLIP_COUNT(checkbuf, effp->clippedCount);
obuf[odone] = checkbuf;
odone++;
--- a/src/dat.c
+++ b/src/dat.c
@@ -25,9 +25,6 @@
#include "st_i.h"
#include <string.h>
-/* float output normalized to approx 1.0 */
-#define FLOATTOLONG (2.147483648e9)
-#define LONGTOFLOAT (1 / FLOATTOLONG)
#define LINEWIDTH 256
/* Private data for dat file */
@@ -129,7 +126,7 @@
st_fail_errno(ft,ST_EOF,"Unable to read sample.");
return (ST_EOF);
}
- sampval *= FLOATTOLONG;
+ sampval *= ST_SAMPLE_MAX;
*buf++ = ST_ROUND_CLIP_COUNT(sampval, ft->clippedCount);
done++;
}
@@ -154,8 +151,7 @@
sprintf(s," %15.8g ",dat->timevalue);
st_writes(ft, s);
for (i=0; i<ft->info.channels; i++) {
- sampval = *buf++ ;
- sampval = sampval * LONGTOFLOAT;
+ sampval = ST_SAMPLE_TO_FLOAT_DDWORD(*buf++, ft->clippedCount);
sprintf(s," %15.8g", sampval);
st_writes(ft, s);
done++;
--- a/src/echo.c
+++ b/src/echo.c
@@ -208,7 +208,7 @@
}
/* Adjust the output volume and size to 24 bit */
d_out = d_out * echo->out_gain;
- out = ST_EFF_24BIT_CLIP_COUNT((st_sample_t) d_out);
+ out = ST_24BIT_CLIP_COUNT((st_sample_t) d_out, effp->clippedCount);
*obuf++ = out * 256;
/* Store input in delay buffer */
echo->delay_buf[echo->counter] = d_in;
@@ -242,7 +242,7 @@
}
/* Adjust the output volume and size to 24 bit */
d_out = d_out * echo->out_gain;
- out = ST_EFF_24BIT_CLIP_COUNT((st_sample_t) d_out);
+ out = ST_24BIT_CLIP_COUNT((st_sample_t) d_out, effp->clippedCount);
*obuf++ = out * 256;
/* Store input in delay buffer */
echo->delay_buf[echo->counter] = d_in;
--- a/src/echos.c
+++ b/src/echos.c
@@ -198,7 +198,7 @@
}
/* Adjust the output volume and size to 24 bit */
d_out = d_out * echos->out_gain;
- out = ST_EFF_24BIT_CLIP_COUNT((st_sample_t) d_out);
+ out = ST_24BIT_CLIP_COUNT((st_sample_t) d_out, effp->clippedCount);
*obuf++ = out * 256;
/* Mix decay of delays and input */
for ( j = 0; j < echos->num_delays; j++ ) {
@@ -238,7 +238,7 @@
}
/* Adjust the output volume and size to 24 bit */
d_out = d_out * echos->out_gain;
- out = ST_EFF_24BIT_CLIP_COUNT((st_sample_t) d_out);
+ out = ST_24BIT_CLIP_COUNT((st_sample_t) d_out, effp->clippedCount);
*obuf++ = out * 256;
/* Mix decay of delays and input */
for ( j = 0; j < echos->num_delays; j++ ) {
--- a/src/equalizer.c
+++ b/src/equalizer.c
@@ -173,7 +173,7 @@
);
eq->y[0] = out;
- ST_EFF_SAMPLE_CLIP_COUNT(out);
+ ST_SAMPLE_CLIP_COUNT(out, effp->clippedCount);
*obuf++ = out;
}
--- a/src/flac.c
+++ b/src/flac.c
@@ -432,9 +432,9 @@
{
switch (encoder->bits_per_sample)
{
- case 8: encoder->decoded_samples[i] = ST_SAMPLE_TO_SIGNED_BYTE(sampleBuffer[i]); break;
- case 16: encoder->decoded_samples[i] = ST_SAMPLE_TO_SIGNED_WORD(sampleBuffer[i]); break;
- case 24: encoder->decoded_samples[i] = ST_SAMPLE_TO_SIGNED_24BIT(sampleBuffer[i]); break;
+ case 8: encoder->decoded_samples[i] = ST_SAMPLE_TO_SIGNED_BYTE(sampleBuffer[i], format->clippedCount); break;
+ case 16: encoder->decoded_samples[i] = ST_SAMPLE_TO_SIGNED_WORD(sampleBuffer[i], format->clippedCount); break;
+ case 24: encoder->decoded_samples[i] = ST_SAMPLE_TO_SIGNED_24BIT(sampleBuffer[i],format->clippedCount); break;
case 32: encoder->decoded_samples[i] = ST_SAMPLE_TO_SIGNED_DWORD(sampleBuffer[i]); break;
}
}
--- a/src/flanger.c
+++ b/src/flanger.c
@@ -227,7 +227,7 @@
flanger->maxsamples] * flanger->decay;
/* Adjust the output volume and size to 24 bit */
d_out = d_out * flanger->out_gain;
- out = ST_EFF_24BIT_CLIP_COUNT((st_sample_t) d_out);
+ out = ST_24BIT_CLIP_COUNT((st_sample_t) d_out, effp->clippedCount);
*obuf++ = out * 256;
/* Mix decay of delay and input */
flanger->flangerbuf[flanger->counter] = d_in;
@@ -260,7 +260,7 @@
flanger->maxsamples] * flanger->decay;
/* Adjust the output volume and size to 24 bit */
d_out = d_out * flanger->out_gain;
- out = ST_EFF_24BIT_CLIP_COUNT((st_sample_t) d_out);
+ out = ST_24BIT_CLIP_COUNT((st_sample_t) d_out, effp->clippedCount);
*obuf++ = out * 256;
/* Mix decay of delay and input */
flanger->flangerbuf[flanger->counter] = d_in;
--- a/src/gsm.c
+++ b/src/gsm.c
@@ -192,7 +192,7 @@
{
while ((p->samplePtr < p->sampleTop) && (done < samp))
*(p->samplePtr)++ =
- ST_SAMPLE_TO_SIGNED_WORD(buf[done++]);
+ ST_SAMPLE_TO_SIGNED_WORD(buf[done++], ft->clippedCount);
if (p->samplePtr == p->sampleTop)
{
--- a/src/hcom.c
+++ b/src/hcom.c
@@ -226,10 +226,7 @@
p->sample = 0;
p->sample = (p->sample + datum) & 0xff;
p->huffcount--;
- if (p->sample == 0)
- *buf++ = ST_UNSIGNED_BYTE_TO_SAMPLE(1);
- else
- *buf++ = ST_UNSIGNED_BYTE_TO_SAMPLE(p->sample);
+ *buf++ = ST_UNSIGNED_BYTE_TO_SAMPLE(p->sample);
p->dictentry = 0;
done++;
len--;
@@ -326,7 +323,7 @@
while (len-- > 0) {
datum = *buf++;
- p->data[p->pos++] = ST_SAMPLE_TO_UNSIGNED_BYTE(datum);
+ p->data[p->pos++] = ST_SAMPLE_TO_UNSIGNED_BYTE(datum, ft->clippedCount);
}
return (save_len - len);
--- a/src/highp.c
+++ b/src/highp.c
@@ -115,7 +115,7 @@
d = highp->A0 * l +
highp->A1 * highp->inm1 +
highp->B1 * highp->outm1;
- ST_EFF_SAMPLE_CLIP_COUNT(d);
+ ST_SAMPLE_CLIP_COUNT(d, effp->clippedCount);
highp->inm1 = l;
highp->outm1 = d;
*obuf++ = d;
--- a/src/lowp.c
+++ b/src/lowp.c
@@ -109,7 +109,7 @@
for(done = 0; done < len; done++) {
l = *ibuf++;
d = lowp->A * l + lowp->B * lowp->outm1;
- ST_EFF_SAMPLE_CLIP_COUNT(d);
+ ST_SAMPLE_CLIP_COUNT(d, effp->clippedCount);
lowp->outm1 = d;
*obuf++ = d;
}
--- a/src/mcompand.c
+++ b/src/mcompand.c
@@ -168,7 +168,7 @@
butterworth->xy_low[chan].y [1] = butterworth->xy_low[chan].y [0];
butterworth->xy_low[chan].y [0] = out;
- ST_EFF_SAMPLE_CLIP_COUNT(out);
+ ST_SAMPLE_CLIP_COUNT(out, effp->clippedCount);
*lowbufptr = out;
@@ -184,7 +184,7 @@
butterworth->xy_high[chan].y [1] = butterworth->xy_high[chan].y [0];
butterworth->xy_high[chan].y [0] = out;
- ST_EFF_SAMPLE_CLIP_COUNT(out);
+ ST_SAMPLE_CLIP_COUNT(out, effp->clippedCount);
/* don't forget polarity reversal of high pass! */
@@ -613,7 +613,7 @@
for (i=0;i<len;++i)
{
out = obuf[i] + abuf[i];
- ST_EFF_SAMPLE_CLIP_COUNT(out);
+ ST_SAMPLE_CLIP_COUNT(out, effp->clippedCount);
obuf[i] = out;
}
oldabuf = abuf;
@@ -638,7 +638,7 @@
*/
for (done = 0; done < maxdrain && l->delay_buf_cnt > 0; done++) {
out = obuf[done] + l->delay_buf[l->delay_buf_ptr++];
- ST_EFF_SAMPLE_CLIP_COUNT(out);
+ ST_SAMPLE_CLIP_COUNT(out, effp->clippedCount);
obuf[done] = out;
l->delay_buf_ptr %= c->delay_buf_size;
l->delay_buf_cnt--;
--- a/src/mp3.c
+++ b/src/mp3.c
@@ -482,8 +482,8 @@
j=0;
for (i=0; i<nsamples; i++)
{
- buffer_l[i]=ST_SAMPLE_TO_SIGNED_WORD(buf[j++]);
- buffer_r[i]=ST_SAMPLE_TO_SIGNED_WORD(buf[j++]);
+ buffer_l[i]=ST_SAMPLE_TO_SIGNED_WORD(buf[j++], ft->clippedCount);
+ buffer_r[i]=ST_SAMPLE_TO_SIGNED_WORD(buf[j++], ft->clippedCount);
}
}
else
@@ -491,7 +491,7 @@
j=0;
for (i=0; i<nsamples; i++)
{
- buffer_l[i]=ST_SAMPLE_TO_SIGNED_WORD(buf[j++]);
+ buffer_l[i]=ST_SAMPLE_TO_SIGNED_WORD(buf[j++], ft->clippedCount);
}
}
--- a/src/noiseprof.c
+++ b/src/noiseprof.c
@@ -130,7 +130,7 @@
int j;
for (j = 0; j < ncopy; j ++) {
chan->window[j+data->bufdata] =
- ST_SAMPLE_TO_FLOAT_DWORD(ibuf[i+j*tracks]);
+ ST_SAMPLE_TO_FLOAT_DWORD(ibuf[i+j*tracks], effp->clippedCount);
}
if (ncopy + data->bufdata == WINDOWSIZE) {
collect_data(data, chan);
--- a/src/noisered.c
+++ b/src/noisered.c
@@ -225,9 +225,8 @@
if (!first) {
for (j = 0; j < use; j ++) {
float s = chan->window[j] + chan->lastwindow[WINDOWSIZE/2 + j];
- ST_EFF_NORMALIZED_CLIP_COUNT(s);
obuf[chan_num + num_chans * j] =
- ST_FLOAT_DWORD_TO_SAMPLE(s);
+ ST_FLOAT_DWORD_TO_SAMPLE(s, effp->clippedCount);
}
free(chan->lastwindow);
} else {
@@ -234,7 +233,7 @@
for (j = 0; j < use; j ++) {
assert(chan->window[j] >= -1 && chan->window[j] <= 1);
obuf[chan_num + num_chans * j] =
- ST_FLOAT_DWORD_TO_SAMPLE(chan->window[j]);
+ ST_FLOAT_DWORD_TO_SAMPLE(chan->window[j], effp->clippedCount);
}
}
chan->lastwindow = chan->window;
@@ -275,7 +274,7 @@
for (j = 0; j < ncopy; j ++) {
chan->window[oldbuf + j] =
- ST_SAMPLE_TO_FLOAT_DWORD(ibuf[i + tracks * j]);
+ ST_SAMPLE_TO_FLOAT_DWORD(ibuf[i + tracks * j], effp->clippedCount);
}
if (!whole_window)
--- a/src/pan.c
+++ b/src/pan.c
@@ -112,7 +112,7 @@
{
double f;
f = 0.5*ibuf_copy[0] + 0.5*ibuf_copy[1];
- ST_EFF_SAMPLE_CLIP_COUNT(f);
+ ST_SAMPLE_CLIP_COUNT(f, effp->clippedCount);
*obuf++ = f;
ibuf_copy += 2;
}
@@ -123,7 +123,7 @@
double f;
f = 0.25*ibuf_copy[0] + 0.25*ibuf_copy[1] +
0.25*ibuf_copy[2] + 0.25*ibuf_copy[3];
- ST_EFF_SAMPLE_CLIP_COUNT(f);
+ ST_SAMPLE_CLIP_COUNT(f, effp->clippedCount);
*obuf++ = f;
ibuf_copy += 4;
}
@@ -141,10 +141,10 @@
double f;
f = left * ibuf_copy[0];
- ST_EFF_SAMPLE_CLIP_COUNT(f);
+ ST_SAMPLE_CLIP_COUNT(f, effp->clippedCount);
obuf[0] = f;
f = right * ibuf_copy[0];
- ST_EFF_SAMPLE_CLIP_COUNT(f);
+ ST_SAMPLE_CLIP_COUNT(f, effp->clippedCount);
obuf[1] = f;
obuf += 2;
ibuf_copy++;
@@ -167,10 +167,10 @@
double f;
f = cll * ibuf_copy[0] + clr * ibuf_copy[1];
- ST_EFF_SAMPLE_CLIP_COUNT(f);
+ ST_SAMPLE_CLIP_COUNT(f, effp->clippedCount);
obuf[0] = f;
f = cr * ibuf_copy[1];
- ST_EFF_SAMPLE_CLIP_COUNT(f);
+ ST_SAMPLE_CLIP_COUNT(f, effp->clippedCount);
obuf[1] = f;
obuf += 2;
ibuf_copy += 2;
@@ -190,10 +190,10 @@
double f;
f = cl * ibuf_copy[0];
- ST_EFF_SAMPLE_CLIP_COUNT(f);
+ ST_SAMPLE_CLIP_COUNT(f, effp->clippedCount);
obuf[0] = f;
f = crl * ibuf_copy[0] + crr * ibuf_copy[1];
- ST_EFF_SAMPLE_CLIP_COUNT(f);
+ ST_SAMPLE_CLIP_COUNT(f, effp->clippedCount);
obuf[1] = f;
obuf += 2;
ibuf_copy += 2;
@@ -220,10 +220,10 @@
/* pan it */
f = cll * ibuf0 + clr * ibuf1;
- ST_EFF_SAMPLE_CLIP_COUNT(f);
+ ST_SAMPLE_CLIP_COUNT(f, effp->clippedCount);
obuf[0] = f;
f = cr * ibuf1;
- ST_EFF_SAMPLE_CLIP_COUNT(f);
+ ST_SAMPLE_CLIP_COUNT(f, effp->clippedCount);
obuf[1] = f;
obuf += 2;
ibuf_copy += 4;
@@ -246,10 +246,10 @@
ibuf1 = 0.5*ibuf_copy[1] + 0.5*ibuf_copy[3];
f = cl * ibuf0;
- ST_EFF_SAMPLE_CLIP_COUNT(f);
+ ST_SAMPLE_CLIP_COUNT(f, effp->clippedCount);
obuf[0] = f;
f = crl * ibuf0 + crr * ibuf1;
- ST_EFF_SAMPLE_CLIP_COUNT(f);
+ ST_SAMPLE_CLIP_COUNT(f, effp->clippedCount);
obuf[1] = f;
obuf += 2;
ibuf_copy += 4;
@@ -275,10 +275,10 @@
double f;
f = cl * ibuf_copy[0];
- ST_EFF_SAMPLE_CLIP_COUNT(f);
+ ST_SAMPLE_CLIP_COUNT(f, effp->clippedCount);
obuf[2] = obuf[0] = f;
f = cr * ibuf_copy[0];
- ST_EFF_SAMPLE_CLIP_COUNT(f);
+ ST_SAMPLE_CLIP_COUNT(f, effp->clippedCount);
ibuf_copy[3] = obuf[1] = f;
obuf += 4;
ibuf_copy++;
@@ -300,10 +300,10 @@
double f;
f = cll * ibuf_copy[0] + clr * ibuf_copy[1];
- ST_EFF_SAMPLE_CLIP_COUNT(f);
+ ST_SAMPLE_CLIP_COUNT(f, effp->clippedCount);
obuf[2] = obuf[0] = f;
f = cr * ibuf_copy[1];
- ST_EFF_SAMPLE_CLIP_COUNT(f);
+ ST_SAMPLE_CLIP_COUNT(f, effp->clippedCount);
ibuf_copy[3] = obuf[1] = f;
obuf += 4;
ibuf_copy += 2;
@@ -323,10 +323,10 @@
double f;
f = cl * ibuf_copy[0];
- ST_EFF_SAMPLE_CLIP_COUNT(f);
+ ST_SAMPLE_CLIP_COUNT(f, effp->clippedCount);
obuf[2] = obuf[0] =f ;
f = crl * ibuf_copy[0] + crr * ibuf_copy[1];
- ST_EFF_SAMPLE_CLIP_COUNT(f);
+ ST_SAMPLE_CLIP_COUNT(f, effp->clippedCount);
ibuf_copy[3] = obuf[1] = f;
obuf += 4;
ibuf_copy += 2;
@@ -349,16 +349,16 @@
double f;
f = cown*ibuf_copy[0] + cright*ibuf_copy[1];
- ST_EFF_SAMPLE_CLIP_COUNT(f);
+ ST_SAMPLE_CLIP_COUNT(f, effp->clippedCount);
obuf[0] = f;
f = cown*ibuf_copy[1] + cright*ibuf_copy[3];
- ST_EFF_SAMPLE_CLIP_COUNT(f);
+ ST_SAMPLE_CLIP_COUNT(f, effp->clippedCount);
obuf[1] = f;
f = cown*ibuf_copy[2] + cright*ibuf_copy[0];
- ST_EFF_SAMPLE_CLIP_COUNT(f);
+ ST_SAMPLE_CLIP_COUNT(f, effp->clippedCount);
obuf[2] = f;
f = cown*ibuf_copy[3] + cright*ibuf_copy[2];
- ST_EFF_SAMPLE_CLIP_COUNT(f);
+ ST_SAMPLE_CLIP_COUNT(f, effp->clippedCount);
obuf[3] = f;
obuf += 4;
ibuf_copy += 4;
@@ -376,16 +376,16 @@
double f;
f = cleft*ibuf_copy[2] + cown*ibuf_copy[0];
- ST_EFF_SAMPLE_CLIP_COUNT(f);
+ ST_SAMPLE_CLIP_COUNT(f, effp->clippedCount);
obuf[0] = f;
f = cleft*ibuf_copy[0] + cown*ibuf_copy[1];
- ST_EFF_SAMPLE_CLIP_COUNT(f);
+ ST_SAMPLE_CLIP_COUNT(f, effp->clippedCount);
obuf[1] = f;
f = cleft*ibuf_copy[3] + cown*ibuf_copy[2];
- ST_EFF_SAMPLE_CLIP_COUNT(f);
+ ST_SAMPLE_CLIP_COUNT(f, effp->clippedCount);
obuf[2] = f;
f = cleft*ibuf_copy[1] + cown*ibuf_copy[3];
- ST_EFF_SAMPLE_CLIP_COUNT(f);
+ ST_SAMPLE_CLIP_COUNT(f, effp->clippedCount);
obuf[3] = f;
obuf += 4;
ibuf_copy += 4;
--- a/src/phaser.c
+++ b/src/phaser.c
@@ -214,7 +214,7 @@
phaser->maxsamples] * phaser->decay * -1.0;
/* Adjust the output volume and size to 24 bit */
d_out = d_in * phaser->out_gain;
- out = ST_EFF_24BIT_CLIP_COUNT((st_sample_t) d_out);
+ out = ST_24BIT_CLIP_COUNT((st_sample_t) d_out, effp->clippedCount);
*obuf++ = out * 256;
/* Mix decay of delay and input */
phaser->phaserbuf[phaser->counter] = d_in;
@@ -247,7 +247,7 @@
phaser->maxsamples] * phaser->decay * -1.0;
/* Adjust the output volume and size to 24 bit */
d_out = d_in * phaser->out_gain;
- out = ST_EFF_24BIT_CLIP_COUNT((st_sample_t) d_out);
+ out = ST_24BIT_CLIP_COUNT((st_sample_t) d_out, effp->clippedCount);
*obuf++ = out * 256;
/* Mix decay of delay and input */
phaser->phaserbuf[phaser->counter] = d_in;
--- a/src/pitch.c
+++ b/src/pitch.c
@@ -496,7 +496,7 @@
float f;
f = pitch->acc[pitch->iacc++];
- ST_EFF_SAMPLE_CLIP_COUNT(f);
+ ST_SAMPLE_CLIP_COUNT(f, effp->clippedCount);
obuf[oindex++] = f;
}
@@ -549,7 +549,7 @@
float f;
f = pitch->acc[pitch->iacc++];
- ST_EFF_SAMPLE_CLIP_COUNT(f);
+ ST_SAMPLE_CLIP_COUNT(f, effp->clippedCount);
obuf[i++] = f;
}
--- a/src/polyphas.c
+++ b/src/polyphas.c
@@ -603,7 +603,7 @@
{
float f;
f = out_buf[k] * ISCALE; /* should clip-limit */
- ST_EFF_SAMPLE_CLIP_COUNT(f);
+ ST_SAMPLE_CLIP_COUNT(f, effp->clippedCount);
*q++ = f;
}
--- a/src/rabbit.c
+++ b/src/rabbit.c
@@ -123,7 +123,7 @@
}
for (i = 0 ; i < *isamp; i++)
- r->data->data_in[r->samples + i] = ST_SAMPLE_TO_FLOAT_DWORD(ibuf[i]);
+ r->data->data_in[r->samples + i] = ST_SAMPLE_TO_FLOAT_DWORD(ibuf[i], effp->clippedCount);
r->samples = newsamples;
r->data->input_frames = r->samples / channels;
@@ -186,7 +186,7 @@
outsamps = min(r->data->output_frames_gen * channels - r->outsamp, *osamp);
for (i = 0; i < outsamps; i++)
- obuf[i] = ST_FLOAT_DWORD_TO_SAMPLE(r->data->data_out[r->outsamp + i]);
+ obuf[i] = ST_FLOAT_DWORD_TO_SAMPLE(r->data->data_out[r->outsamp + i], effp->clippedCount);
*osamp = (st_size_t)outsamps;
r->outsamp += outsamps;
--- a/src/raw.c
+++ b/src/raw.c
@@ -54,10 +54,10 @@
0x3F, 0xBF, 0x7F, 0xFF
};
-#define ST_ULAW_BYTE_TO_SAMPLE(d) ST_SIGNED_WORD_TO_SAMPLE(st_ulaw2linear16(d))
-#define ST_ALAW_BYTE_TO_SAMPLE(d) ST_SIGNED_WORD_TO_SAMPLE(st_alaw2linear16(d))
-#define ST_SAMPLE_TO_ULAW_BYTE(d) st_14linear2ulaw(ST_SAMPLE_TO_SIGNED_WORD(d) >> 2)
-#define ST_SAMPLE_TO_ALAW_BYTE(d) st_13linear2alaw(ST_SAMPLE_TO_SIGNED_WORD(d) >> 3)
+#define ST_ULAW_BYTE_TO_SAMPLE(d) ST_SIGNED_WORD_TO_SAMPLE(st_ulaw2linear16(d))
+#define ST_ALAW_BYTE_TO_SAMPLE(d) ST_SIGNED_WORD_TO_SAMPLE(st_alaw2linear16(d))
+#define ST_SAMPLE_TO_ULAW_BYTE(d,c) st_14linear2ulaw(ST_SAMPLE_TO_SIGNED_WORD(d,c) >> 2)
+#define ST_SAMPLE_TO_ALAW_BYTE(d,c) st_13linear2alaw(ST_SAMPLE_TO_SIGNED_WORD(d,c) >> 3)
/* Some hardware sends MSB last. These account for that */
#define ST_INVERT_ULAW_BYTE_TO_SAMPLE(d) \
@@ -64,10 +64,10 @@
ST_SIGNED_WORD_TO_SAMPLE(st_ulaw2linear16(cswap[d]))
#define ST_INVERT_ALAW_BYTE_TO_SAMPLE(d) \
ST_SIGNED_WORD_TO_SAMPLE(st_alaw2linear16(cswap[d]))
-#define ST_SAMPLE_TO_INVERT_ULAW_BYTE(d) \
- cswap[st_14linear2ulaw(ST_SAMPLE_TO_SIGNED_WORD(d) >> 2)]
-#define ST_SAMPLE_TO_INVERT_ALAW_BYTE(d) \
- cswap[st_13linear2alaw(ST_SAMPLE_TO_SIGNED_WORD(d) >> 3)]
+#define ST_SAMPLE_TO_INVERT_ULAW_BYTE(d,c) \
+ cswap[st_14linear2ulaw(ST_SAMPLE_TO_SIGNED_WORD(d,c) >> 2)]
+#define ST_SAMPLE_TO_INVERT_ALAW_BYTE(d,c) \
+ cswap[st_13linear2alaw(ST_SAMPLE_TO_SIGNED_WORD(d,c) >> 3)]
static void rawdefaults(ft_t ft);
@@ -134,7 +134,7 @@
return ST_SUCCESS;
}
-void st_ub_read_buf(st_sample_t *buf1, char const * buf2, st_size_t len, char swap)
+void st_ub_read_buf(st_sample_t *buf1, char const * buf2, st_size_t len, char swap, st_size_t * clippedCount)
{
while (len)
{
@@ -148,7 +148,7 @@
}
}
-void st_sb_read_buf(st_sample_t *buf1, char const * buf2, st_size_t len, char swap)
+void st_sb_read_buf(st_sample_t *buf1, char const * buf2, st_size_t len, char swap, st_size_t * clippedCount)
{
while (len)
{
@@ -162,8 +162,7 @@
}
}
-void st_ulaw_read_buf(st_sample_t *buf1, char const * buf2, st_size_t len,
- char swap)
+void st_ulaw_read_buf(st_sample_t *buf1, char const * buf2, st_size_t len, char swap, st_size_t * clippedCount)
{
while (len)
{
@@ -177,8 +176,7 @@
}
}
-void st_alaw_read_buf(st_sample_t *buf1, char const * buf2, st_size_t len,
- char swap)
+void st_alaw_read_buf(st_sample_t *buf1, char const * buf2, st_size_t len, char swap, st_size_t * clippedCount)
{
while (len)
{
@@ -192,8 +190,7 @@
}
}
-void st_inv_ulaw_read_buf(st_sample_t *buf1, char const * buf2, st_size_t len,
- char swap)
+void st_inv_ulaw_read_buf(st_sample_t *buf1, char const * buf2, st_size_t len, char swap, st_size_t * clippedCount)
{
while (len)
{
@@ -207,8 +204,7 @@
}
}
-void st_inv_alaw_read_buf(st_sample_t *buf1, char const * buf2, st_size_t len,
- char swap)
+void st_inv_alaw_read_buf(st_sample_t *buf1, char const * buf2, st_size_t len, char swap, st_size_t * clippedCount)
{
while (len)
{
@@ -223,7 +219,7 @@
}
-void st_uw_read_buf(st_sample_t *buf1, char const * buf2, st_size_t len, char swap)
+void st_uw_read_buf(st_sample_t *buf1, char const * buf2, st_size_t len, char swap, st_size_t * clippedCount)
{
while (len)
{
@@ -239,7 +235,7 @@
}
}
-void st_sw_read_buf(st_sample_t *buf1, char const * buf2, st_size_t len, char swap)
+void st_sw_read_buf(st_sample_t *buf1, char const * buf2, st_size_t len, char swap, st_size_t * clippedCount)
{
while (len)
{
@@ -275,7 +271,7 @@
-void st_u24_read_buf(st_sample_t * buf1, char const * buf2, st_size_t len, char const swap)
+void st_u24_read_buf(st_sample_t * buf1, char const * buf2, st_size_t len, char const swap, st_size_t * clippedCount)
{
while (len--)
{
@@ -286,7 +282,7 @@
-void st_s24_read_buf(st_sample_t * buf1, char const * buf2, st_size_t len, char const swap)
+void st_s24_read_buf(st_sample_t * buf1, char const * buf2, st_size_t len, char const swap, st_size_t * clippedCount)
{
while (len--)
{
@@ -297,7 +293,7 @@
-void st_udw_read_buf(st_sample_t *buf1, char const * buf2, st_size_t len, char swap)
+void st_udw_read_buf(st_sample_t *buf1, char const * buf2, st_size_t len, char swap, st_size_t * clippedCount)
{
while (len)
{
@@ -313,7 +309,7 @@
}
}
-void st_dw_read_buf(st_sample_t *buf1, char const * buf2, st_size_t len, char swap)
+void st_dw_read_buf(st_sample_t *buf1, char const * buf2, st_size_t len, char swap, st_size_t * clippedCount)
{
while (len)
{
@@ -329,7 +325,7 @@
}
}
-void st_f32_read_buf(st_sample_t *buf1, char const * buf2, st_size_t len, char swap)
+void st_f32_read_buf(st_sample_t *buf1, char const * buf2, st_size_t len, char swap, st_size_t * clippedCount)
{
while (len)
{
@@ -340,12 +336,12 @@
if (swap)
datum = st_swapf(datum);
- *buf1++ = ST_FLOAT_DWORD_TO_SAMPLE(datum);
+ *buf1++ = ST_FLOAT_DWORD_TO_SAMPLE(datum, *clippedCount);
len--;
}
}
-void st_f64_read_buf(st_sample_t *buf1, char const * buf2, st_size_t len, char swap)
+void st_f64_read_buf(st_sample_t *buf1, char const * buf2, st_size_t len, char swap, st_size_t * clippedCount)
{
while (len)
{
@@ -357,7 +353,7 @@
if (swap)
datum = st_swapd(datum);
- *buf1++ = ST_FLOAT_DDWORD_TO_SAMPLE(datum);
+ *buf1++ = ST_FLOAT_DDWORD_TO_SAMPLE(datum, *clippedCount);
len--;
}
}
@@ -373,7 +369,7 @@
st_ssize_t st_rawread(ft_t ft, st_sample_t *buf, st_size_t nsamp)
{
st_size_t len, done = 0;
- void (*read_buf)(st_sample_t *, char const *, st_size_t, char) = 0;
+ void (*read_buf)(st_sample_t *, char const *, st_size_t, char, st_size_t *) = 0;
size_t i;
if (nsamp < 0)
@@ -478,7 +474,7 @@
len = min((st_size_t)nsamp,(ft->file.count-ft->file.pos)/ft->info.size);
if (len)
{
- read_buf(buf + done, ft->file.buf + ft->file.pos, len, ft->swap);
+ read_buf(buf + done, ft->file.buf + ft->file.pos, len, ft->swap, &ft->clippedCount);
ft->file.pos += (len*ft->info.size);
done += len;
}
@@ -510,7 +506,7 @@
len = min((st_size_t)nsamp - done,(ft->file.count-ft->file.pos)/ft->info.size);
if (len)
{
- read_buf(buf + done, ft->file.buf + ft->file.pos, len, ft->swap);
+ read_buf(buf + done, ft->file.buf + ft->file.pos, len, ft->swap, &ft->clippedCount);
ft->file.pos += (len*ft->info.size);
done += len;
}
@@ -531,71 +527,71 @@
return ST_SUCCESS;
}
-void st_ub_write_buf(char* buf1, st_sample_t const * buf2, st_size_t len, char swap)
+void st_ub_write_buf(char* buf1, st_sample_t const * buf2, st_size_t len, char swap, st_size_t * clippedCount)
{
while (len)
{
- *(uint8_t *)buf1++ = ST_SAMPLE_TO_UNSIGNED_BYTE(*buf2++);
+ *(uint8_t *)buf1++ = ST_SAMPLE_TO_UNSIGNED_BYTE(*buf2++, *clippedCount);
len--;
}
}
-void st_sb_write_buf(char *buf1, st_sample_t const * buf2, st_size_t len, char swap)
+void st_sb_write_buf(char *buf1, st_sample_t const * buf2, st_size_t len, char swap, st_size_t * clippedCount)
{
while (len)
{
- *(int8_t *)buf1++ = ST_SAMPLE_TO_SIGNED_BYTE(*buf2++);
+ *(int8_t *)buf1++ = ST_SAMPLE_TO_SIGNED_BYTE(*buf2++, *clippedCount);
len--;
}
}
void st_ulaw_write_buf(char *buf1, st_sample_t const * buf2, st_size_t len,
- char swap)
+ char swap, st_size_t * clippedCount)
{
while (len)
{
- *(uint8_t *)buf1++ = ST_SAMPLE_TO_ULAW_BYTE(*buf2++);
+ *(uint8_t *)buf1++ = ST_SAMPLE_TO_ULAW_BYTE(*buf2++, *clippedCount);
len--;
}
}
void st_alaw_write_buf(char *buf1, st_sample_t const * buf2, st_size_t len,
- char swap)
+ char swap, st_size_t * clippedCount)
{
while (len)
{
- *(uint8_t *)buf1++ = ST_SAMPLE_TO_ALAW_BYTE(*buf2++);
+ *(uint8_t *)buf1++ = ST_SAMPLE_TO_ALAW_BYTE(*buf2++, *clippedCount);
len--;
}
}
void st_inv_ulaw_write_buf(char *buf1, st_sample_t const * buf2, st_size_t len,
- char swap)
+ char swap, st_size_t * clippedCount)
{
while (len)
{
- *(uint8_t *)buf1++ = ST_SAMPLE_TO_INVERT_ULAW_BYTE(*buf2++);
+ *(uint8_t *)buf1++ = ST_SAMPLE_TO_INVERT_ULAW_BYTE(*buf2++, *clippedCount);
len--;
}
}
void st_inv_alaw_write_buf(char *buf1, st_sample_t const * buf2, st_size_t len,
- char swap)
+ char swap, st_size_t * clippedCount)
{
while (len)
{
- *(uint8_t *)buf1++ = ST_SAMPLE_TO_INVERT_ALAW_BYTE(*buf2++);
+ *(uint8_t *)buf1++ = ST_SAMPLE_TO_INVERT_ALAW_BYTE(*buf2++, *clippedCount);
len--;
}
}
-void st_uw_write_buf(char *buf1, st_sample_t const * buf2, st_size_t len, char swap)
+void st_uw_write_buf(char *buf1, st_sample_t const * buf2, st_size_t len, char swap, st_size_t * clippedCount)
{
while (len)
{
uint16_t datum;
- datum = ST_SAMPLE_TO_UNSIGNED_WORD(*buf2++);
+ datum = ST_SAMPLE_TO_UNSIGNED_WORD(*buf2++, *clippedCount);
if (swap)
datum = st_swapw(datum);
*(uint16_t *)buf1 = datum;
@@ -605,13 +601,13 @@
}
}
-void st_sw_write_buf(char *buf1, st_sample_t const * buf2, st_size_t len, char swap)
+void st_sw_write_buf(char *buf1, st_sample_t const * buf2, st_size_t len, char swap, st_size_t * clippedCount)
{
while (len)
{
int16_t datum;
- datum = ST_SAMPLE_TO_SIGNED_WORD(*buf2++);
+ datum = ST_SAMPLE_TO_SIGNED_WORD(*buf2++, *clippedCount);
if (swap)
datum = st_swapw(datum);
*(int16_t *)buf1 = datum;
@@ -643,11 +639,11 @@
-void st_u24_write_buf(char * buf1, st_sample_t const * buf2, st_size_t len, char const swap)
+void st_u24_write_buf(char * buf1, st_sample_t const * buf2, st_size_t len, char const swap, st_size_t * clippedCount)
{
while (len--)
{
- int24_t datum = ST_SAMPLE_TO_UNSIGNED_24BIT(*buf2++);
+ int24_t datum = ST_SAMPLE_TO_UNSIGNED_24BIT(*buf2++, *clippedCount);
st_24_write_one(&buf1, datum, swap);
}
}
@@ -654,11 +650,11 @@
-void st_s24_write_buf(char * buf1, st_sample_t const * buf2, st_size_t len, char const swap)
+void st_s24_write_buf(char * buf1, st_sample_t const * buf2, st_size_t len, char const swap, st_size_t * clippedCount)
{
while (len--)
{
- int24_t datum = ST_SAMPLE_TO_SIGNED_24BIT(*buf2++);
+ int24_t datum = ST_SAMPLE_TO_SIGNED_24BIT(*buf2++, *clippedCount);
st_24_write_one(&buf1, datum, swap);
}
}
@@ -665,7 +661,7 @@
-void st_udw_write_buf(char *buf1, st_sample_t const * buf2, st_size_t len, char swap)
+void st_udw_write_buf(char *buf1, st_sample_t const * buf2, st_size_t len, char swap, st_size_t * clippedCount)
{
while (len)
{
@@ -681,7 +677,7 @@
}
}
-void st_dw_write_buf(char *buf1, st_sample_t const * buf2, st_size_t len, char swap)
+void st_dw_write_buf(char *buf1, st_sample_t const * buf2, st_size_t len, char swap, st_size_t * clippedCount)
{
while (len)
{
@@ -697,13 +693,13 @@
}
}
-void st_f32_write_buf(char *buf1, st_sample_t const * buf2, st_size_t len, char swap)
+void st_f32_write_buf(char *buf1, st_sample_t const * buf2, st_size_t len, char swap, st_size_t * clippedCount)
{
while (len)
{
float datum;
- datum = ST_SAMPLE_TO_FLOAT_DWORD(*buf2++);
+ datum = ST_SAMPLE_TO_FLOAT_DWORD(*buf2++, *clippedCount);
if (swap)
datum = st_swapf(datum);
*(float *)buf1 = datum;
@@ -713,13 +709,13 @@
}
}
-void st_f64_write_buf(char *buf1, st_sample_t const * buf2, st_size_t len, char swap)
+void st_f64_write_buf(char *buf1, st_sample_t const * buf2, st_size_t len, char swap, st_size_t * clippedCount)
{
while (len)
{
double datum;
- datum = ST_SAMPLE_TO_FLOAT_DDWORD(*buf2++);
+ datum = ST_SAMPLE_TO_FLOAT_DDWORD(*buf2++, *clippedCount);
if (swap)
datum = st_swapf(datum);
*(double *)buf1 = datum;
@@ -751,7 +747,7 @@
st_ssize_t st_rawwrite(ft_t ft, const st_sample_t *buf, st_size_t nsamp)
{
st_size_t len, done = 0;
- void (*write_buf)(char *, st_sample_t const *, st_size_t, char) = 0;
+ void (*write_buf)(char *, st_sample_t const *, st_size_t, char, st_size_t *) = 0;
switch(ft->info.size) {
case ST_SIZE_BYTE:
@@ -856,7 +852,7 @@
len = min(nsamp-done,(ft->file.size-ft->file.pos)/ft->info.size);
if (len)
{
- write_buf(ft->file.buf + ft->file.pos, buf+done, len, ft->swap);
+ write_buf(ft->file.buf + ft->file.pos, buf+done, len, ft->swap, &ft->clippedCount);
ft->file.pos += (len*ft->info.size);
done += len;
}
--- a/src/resample.c
+++ b/src/resample.c
@@ -401,7 +401,7 @@
// orig: *obuf++ = r->Y[i] * ISCALE;
double ftemp = r->Y[i] * ISCALE;
- ST_EFF_SAMPLE_CLIP_COUNT(ftemp);
+ ST_SAMPLE_CLIP_COUNT(ftemp, effp->clippedCount);
*obuf++ = ftemp;
}
--- a/src/reverb.c
+++ b/src/reverb.c
@@ -229,7 +229,7 @@
d_in +=
reverb->reverbbuf[(i + reverb->maxsamples - reverb->samples[j]) % reverb->maxsamples] * reverb->decay[j];
d_out = d_in * reverb->out_gain;
- out = ST_EFF_24BIT_CLIP_COUNT((st_sample_t) d_out);
+ out = ST_24BIT_CLIP_COUNT((st_sample_t) d_out, effp->clippedCount);
*obuf++ = out * 256;
reverb->reverbbuf[i] = d_in;
i++; /* XXX need a % maxsamples here ? */
@@ -261,10 +261,10 @@
d_in +=
reverb->reverbbuf[(i + reverb->maxsamples - reverb->samples[j]) % reverb->maxsamples] * reverb->decay[j];
d_out = d_in * reverb->out_gain;
- out = ST_EFF_24BIT_CLIP_COUNT((st_sample_t) d_out);
+ out = ST_24BIT_CLIP_COUNT((st_sample_t) d_out, effp->clippedCount);
obuf[done++] = out * 256;
reverb->reverbbuf[i] = d_in;
- l = ST_EFF_24BIT_CLIP_COUNT((st_sample_t) d_in);
+ l = ST_24BIT_CLIP_COUNT((st_sample_t) d_in, effp->clippedCount);
reverb->pppl = reverb->ppl;
reverb->ppl = reverb->pl;
reverb->pl = l;
--- a/src/silence.c
+++ b/src/silence.c
@@ -325,6 +325,7 @@
{
double ratio;
int rc;
+ st_sample_t dummy_clipped_count = 0;
/* When scaling low bit data, noise values got scaled way up */
/* Only consider the original bits when looking for silence */
@@ -331,12 +332,16 @@
switch(effp->ininfo.size)
{
case ST_SIZE_BYTE:
- value = ST_SAMPLE_TO_SIGNED_BYTE(value);
+ value = ST_SAMPLE_TO_SIGNED_BYTE(value, dummy_clipped_count);
ratio = (double)abs(value) / (double)ST_INT8_MAX;
break;
case ST_SIZE_WORD:
- value = ST_SAMPLE_TO_SIGNED_WORD(value);
+ value = ST_SAMPLE_TO_SIGNED_WORD(value, dummy_clipped_count);
ratio = (double)abs(value) / (double)ST_INT16_MAX;
+ break;
+ case ST_SIZE_24BIT:
+ value = ST_SAMPLE_TO_SIGNED_24BIT(value, dummy_clipped_count);
+ ratio = (double)abs(value) / (double)ST_INT24_MAX;
break;
case ST_SIZE_DWORD:
value = ST_SAMPLE_TO_SIGNED_DWORD(value);
--- a/src/skel.c
+++ b/src/skel.c
@@ -158,7 +158,7 @@
case ST_ENCODING_UNSIGNED:
while(len--)
{
- len = st_writeb(ft, ST_SAMPLE_TO_UNSIGNED_BYTE(*buff++));
+ len = st_writeb(ft, ST_SAMPLE_TO_UNSIGNED_BYTE(*buff++, ft->clippedCount));
if (len == ST_EOF)
break;
}
--- a/src/smp.c
+++ b/src/smp.c
@@ -397,7 +397,7 @@
st_ssize_t done = 0;
while(done < len) {
- datum = (int) ST_SAMPLE_TO_SIGNED_WORD(*buf++);
+ datum = (int) ST_SAMPLE_TO_SIGNED_WORD(*buf++, ft->clippedCount);
st_writew(ft, datum);
smp->NoOfSamps++;
done++;
--- a/src/sox.c
+++ b/src/sox.c
@@ -938,12 +938,17 @@
{
/* We no longer have any info about this file as we've just
* st_close'd it, so just refer to file number: */
- st_warn("Input file # %i reported an error whilst it was being closed.", f);
+ st_warn("Input file # %i reported an error whilst it was being closed.", f + 1);
}
}
if (writing)
{
+ if (file_desc[f]->clippedCount != 0)
+ {
+ st_warn("%s: %u values clipped on output", file_desc[f]->filename, file_desc[f]->clippedCount);
+ }
+
/* problem closing output file, just warn user since we
* are exiting anyways.
*/
--- a/src/speed.c
+++ b/src/speed.c
@@ -173,7 +173,7 @@
f = cub(speed->cbuf[0], speed->cbuf[1],
speed->cbuf[2], speed->cbuf[3],
speed->frac);
- ST_EFF_SAMPLE_CLIP_COUNT(f);
+ ST_SAMPLE_CLIP_COUNT(f, effp->clippedCount);
obuf[i] = f;
}
--- a/src/st.h
+++ b/src/st.h
@@ -15,6 +15,10 @@
#include <stdlib.h>
#include "ststdint.h"
+#ifndef __GNUC__
+# define __attribute__(x) /*NOTHING*/
+#endif
+
/* C language enhancements: */
/* Boolean type, compatible with C++ */
@@ -37,43 +41,88 @@
/* Array-length operator */
#define array_length(a) (sizeof(a)/sizeof(a[0]))
-typedef int32_t st_sample_t;
-typedef uint32_t st_size_t;
-typedef int32_t st_ssize_t;
-typedef uint32_t st_rate_t;
+typedef int32_t int24_t; /* But beware of the extra byte. */
+typedef uint32_t uint24_t; /* ditto */
-typedef int32_t int24_t;
-typedef uint32_t uint24_t;
+#define ST_INT_MIN(bits) (1L <<((bits)-1))
+#define ST_INT_MAX(bits) (-1UL>>(33-(bits)))
+#define ST_UINT_MAX(bits) (ST_INT_MIN(bits)|ST_INT_MAX(bits))
+#define ST_INT8_MAX ST_INT_MAX(8)
+#define ST_INT16_MAX ST_INT_MAX(16)
+#define ST_INT24_MAX ST_INT_MAX(24)
+#define ST_INT32_MAX ST_INT_MAX(32)
+#define ST_INT64_MAX 0x7fffffffffffffffLL /* Not in use yet */
+
+typedef int32_t st_sample_t;
/* 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_SCALE 2147483648.0
+#define ST_SAMPLE_MAX (st_sample_t)ST_INT_MAX(32)
+#define ST_SAMPLE_MIN (st_sample_t)ST_INT_MIN(32)
-#define ST_UNSIGNED_BYTE_TO_SAMPLE(d) ((st_sample_t)((d) ^ 0x80) << 24)
-#define ST_SIGNED_BYTE_TO_SAMPLE(d) ((st_sample_t)(d) << 24)
-#define ST_UNSIGNED_WORD_TO_SAMPLE(d) ((st_sample_t)((d) ^ 0x8000) << 16)
-#define ST_SIGNED_WORD_TO_SAMPLE(d) ((st_sample_t)(d) << 16)
-#define ST_UNSIGNED_24BIT_TO_SAMPLE(d) ((st_sample_t)((d) ^ 0x800000L) << 8)
-#define ST_SIGNED_24BIT_TO_SAMPLE(d) ((st_sample_t)(d) << 8)
-#define ST_UNSIGNED_DWORD_TO_SAMPLE(d) ((st_sample_t)((d) ^ 0x80000000L))
-#define ST_SIGNED_DWORD_TO_SAMPLE(d) ((st_sample_t)d)
-#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)
-#define ST_SAMPLE_TO_SIGNED_WORD(d) ((int16_t)((d) >> 16))
-#define ST_SAMPLE_TO_UNSIGNED_24BIT(d) ((uint24_t)((d) >> 8) ^ 0x800000L)
-#define ST_SAMPLE_TO_SIGNED_24BIT(d) ((int24_t)((d) >> 8))
-#define ST_SAMPLE_TO_UNSIGNED_DWORD(d) ((uint32_t)(d) ^ 0x80000000L)
-#define ST_SAMPLE_TO_SIGNED_DWORD(d) ((int32_t)(d))
-/* FIXME: This is an approximation because its impossible to
- * to reach 1.
+
+
+/* Conversions: Linear PCM <--> st_sample_t
+ *
+ * I/O I/O st_sample_t Clips? I/O st_sample_t Clips?
+ * Format Minimum Minimum I O Maximum Maximum I O
+ * ------ --------- ------------ -- -- -------- ------------ -- --
+ * Float -1 -1.00000000047 y y 1 1 y n
+ * Byte -128 -128 n n 127 127.9999999 n y
+ * Word -32768 -32768 n n 32767 32767.99998 n y
+ * 24bit -8388608 -8388608 n n 8388607 8388607.996 n y
+ * Dword -2147483648 -2147483648 n n 2147483647 2147483647 n n
+ *
+ * Conversions are as accurate as possible (with rounding).
+ *
+ * Rounding: halves toward +inf, all others to nearest integer.
+ *
+ * Clips? shows whether on not there is the possibility of a conversion
+ * clipping to the minimum or maximum value when inputing from or outputing
+ * to a given type.
+ *
+ * Unsigned integers are converted to and from signed integers by flipping
+ * the upper-most bit then treating them as signed integers.
*/
-#define ST_SAMPLE_TO_FLOAT_DWORD(d) ((float)(d/(ST_SAMPLE_FLOAT_SCALE)))
-#define ST_SAMPLE_TO_FLOAT_DDWORD(d) ((double)((double)d/(ST_SAMPLE_FLOAT_SCALE)))
+/* Temporary variables to prevent multiple evaluation of macro arguments: */
+static st_sample_t st_macro_temp_sample __attribute__((unused));
+static double st_macro_temp_double __attribute__((unused));
+
+#define ST_SAMPLE_NEG ST_INT_MIN(32)
+#define ST_SAMPLE_TO_UNSIGNED(bits,d,clips) \
+ (uint##bits##_t)( \
+ st_macro_temp_sample=d, \
+ st_macro_temp_sample>(st_sample_t)(ST_SAMPLE_MAX-(1UL<<(31-bits)))? \
+ ++(clips),ST_UINT_MAX(bits): \
+ ((uint32_t)(st_macro_temp_sample^ST_SAMPLE_NEG)+(1UL<<(31-bits)))>>(32-bits))
+#define ST_SAMPLE_TO_SIGNED(bits,d,clips) \
+ (int##bits##_t)(ST_SAMPLE_TO_UNSIGNED(bits,d,clips)^ST_INT_MIN(bits))
+#define ST_SIGNED_TO_SAMPLE(bits,d)((st_sample_t)(d)<<(32-bits))
+#define ST_UNSIGNED_TO_SAMPLE(bits,d)(ST_SIGNED_TO_SAMPLE(bits,d)^ST_SAMPLE_NEG)
+
+#define ST_UNSIGNED_BYTE_TO_SAMPLE(d) ST_UNSIGNED_TO_SAMPLE(8,d)
+#define ST_SIGNED_BYTE_TO_SAMPLE(d) ST_SIGNED_TO_SAMPLE(8,d)
+#define ST_UNSIGNED_WORD_TO_SAMPLE(d) ST_UNSIGNED_TO_SAMPLE(16,d)
+#define ST_SIGNED_WORD_TO_SAMPLE(d) ST_SIGNED_TO_SAMPLE(16,d)
+#define ST_UNSIGNED_24BIT_TO_SAMPLE(d) ST_UNSIGNED_TO_SAMPLE(24,d)
+#define ST_SIGNED_24BIT_TO_SAMPLE(d) ST_SIGNED_TO_SAMPLE(24,d)
+#define ST_UNSIGNED_DWORD_TO_SAMPLE(d) (st_sample_t)((d)^ST_SAMPLE_NEG)
+#define ST_SIGNED_DWORD_TO_SAMPLE(d) (st_sample_t)(d)
+#define ST_FLOAT_DWORD_TO_SAMPLE ST_FLOAT_DDWORD_TO_SAMPLE
+#define ST_FLOAT_DDWORD_TO_SAMPLE(d,clips) (st_macro_temp_double=d,st_macro_temp_double<-1?++(clips),(-ST_SAMPLE_MAX):st_macro_temp_double>1?++(clips),ST_SAMPLE_MAX:(st_sample_t)((uint32_t)((double)(st_macro_temp_double)*ST_SAMPLE_MAX+(ST_SAMPLE_MAX+.5))-ST_SAMPLE_MAX))
+#define ST_SAMPLE_TO_UNSIGNED_BYTE(d,clips) ST_SAMPLE_TO_UNSIGNED(8,d,clips)
+#define ST_SAMPLE_TO_SIGNED_BYTE(d,clips) ST_SAMPLE_TO_SIGNED(8,d,clips)
+#define ST_SAMPLE_TO_UNSIGNED_WORD(d,clips) ST_SAMPLE_TO_UNSIGNED(16,d,clips)
+#define ST_SAMPLE_TO_SIGNED_WORD(d,clips) ST_SAMPLE_TO_SIGNED(16,d,clips)
+#define ST_SAMPLE_TO_UNSIGNED_24BIT(d,clips) ST_SAMPLE_TO_UNSIGNED(24,d,clips)
+#define ST_SAMPLE_TO_SIGNED_24BIT(d,clips) ST_SAMPLE_TO_SIGNED(24,d,clips)
+#define ST_SAMPLE_TO_UNSIGNED_DWORD(d) (uint32_t)((d)^ST_SAMPLE_NEG)
+#define ST_SAMPLE_TO_SIGNED_DWORD(d) (int32_t)(d)
+#define ST_SAMPLE_TO_FLOAT_DWORD (float)ST_SAMPLE_TO_FLOAT_DDWORD
+#define ST_SAMPLE_TO_FLOAT_DDWORD(d,clips) (st_macro_temp_sample=d,st_macro_temp_sample==ST_SAMPLE_MIN?++(clips),-1.0:((double)(st_macro_temp_sample)*(1.0/ST_SAMPLE_MAX)))
+
+
+
/* MACRO to clip a data type that is greater then st_sample_t to
* st_sample_t's limits and increment a counter if clipping occurs..
*/
@@ -99,29 +148,22 @@
((l) >= ((st_sample_t)1 << 23)? ++(clips), ((st_sample_t)1 << 23) - 1 : \
(l) <=-((st_sample_t)1 << 23)? ++(clips),-((st_sample_t)1 << 23) + 1 : (l))
-/* MACRO to clip a normalized floating point data between 1.0 and -1.0
- * to those limits and increment a counter when clipping occurs.
- */
-#define ST_NORMALIZED_CLIP_COUNT(samp, clips) \
- do { \
- if (samp > 1) \
- { samp = 1; clips++; } \
- else if (samp < -1) \
- { samp = -1; clips++; } \
- } while (0)
-/* MACROs for effects where standard clip counting and reporting is used. */
-#define ST_EFF_SAMPLE_CLIP_COUNT(s) ST_SAMPLE_CLIP_COUNT(s, effp->clippedCount)
-#define ST_EFF_24BIT_CLIP_COUNT(s) ST_24BIT_CLIP_COUNT(s, effp->clippedCount)
-#define ST_EFF_ROUND_CLIP_COUNT(s) ST_ROUND_CLIP_COUNT(s, effp->clippedCount)
-#define ST_EFF_NORMALIZED_CLIP_COUNT(s) ST_NORMALIZED_CLIP_COUNT(s, effp->clippedCount)
+typedef uint32_t st_size_t;
/* Maximum value size type can hold. (Minimum is 0). */
#define ST_SIZE_MAX 0xffffffffL
+typedef int32_t st_ssize_t;
/* Minimum and maximum value signed size type can hold. */
#define ST_SSIZE_MAX 0x7fffffffL
#define ST_SSIZE_MIN (-ST_SSIZE_MAX - 1L)
+
+typedef uint32_t st_rate_t;
+/* Warning, this is a MAX value used in the library. Each format and
+ * effect may have its own limitations of rate.
+ */
+#define ST_MAXRATE (50UL * 1024) /* maximum sample rate in library */
typedef enum {
ST_ENCODING_UNKNOWN ,
--- a/src/st_i.h
+++ b/src/st_i.h
@@ -42,6 +42,7 @@
#ifndef HAVE_STRCASECMP
int strcasecmp(const char *s1, const char *s2);
+int strncasecmp(char const * s1, char const * s2, size_t n);
#endif
#ifndef HAVE_STRDUP
@@ -124,11 +125,6 @@
#define ST_IS_LITTLEENDIAN 1
#endif
-/* Warning, this is a MAX value used in the library. Each format and
- * effect may have its own limitations of rate.
- */
-#define ST_MAXRATE 50L * 1024 /* maximum sample rate in library */
-
#ifndef M_PI
#define M_PI 3.14159265358979323846
#endif
@@ -135,11 +131,6 @@
#ifndef M_PI_2
#define M_PI_2 1.57079632679489661923 /* pi/2 */
#endif
-
-#define ST_INT8_MAX (127)
-#define ST_INT16_MAX (32676)
-#define ST_INT32_MAX (2147483647)
-#define ST_INT64_MAX (9223372036854775807)
/* The following is used at times in libst when alloc()ing buffers
* to perform file I/O. It can be useful to pass in similar sized
--- a/src/stat.c
+++ b/src/stat.c
@@ -170,7 +170,7 @@
{
for (x = 0; x < len; x++)
{
- stat->re_in[stat->fft_offset++] = ST_SAMPLE_TO_FLOAT_DWORD(ibuf[x]);
+ stat->re_in[stat->fft_offset++] = ST_SAMPLE_TO_FLOAT_DWORD(ibuf[x], effp->clippedCount);
if (stat->fft_offset >= stat->fft_size)
{
--- a/src/stretch.c
+++ b/src/stretch.c
@@ -321,7 +321,7 @@
{
float f;
f = stretch->obuf[stretch->oindex++];
- ST_EFF_SAMPLE_CLIP_COUNT(f);
+ ST_SAMPLE_CLIP_COUNT(f, effp->clippedCount);
obuf[oindex++] = f;
}
@@ -376,7 +376,7 @@
float f;
f = stretch->obuf[stretch->oindex++];
- ST_EFF_SAMPLE_CLIP_COUNT(f);
+ ST_SAMPLE_CLIP_COUNT(f, effp->clippedCount);
obuf[oindex++] = f;
}
--- a/src/synth.c
+++ b/src/synth.c
@@ -270,7 +270,6 @@
/* set default parameters */
synth->length = 0; /* use length of input file */
synth->length_str = 0;
- synth->max = ST_SAMPLE_MAX;
for(c=0;c<MAXCHAN;c++){
synth->freq[c] = 440.0;
synth->freq2[c] = 440.0;
@@ -398,6 +397,9 @@
int i;
int c;
synth_t synth = (synth_t) effp->priv;
+ int shift_for_max = (4 - min(effp->outinfo.size, 4)) << 3;
+
+ synth->max = (ST_SAMPLE_MAX >> shift_for_max) << shift_for_max;
st_initrand();
--- a/src/tests.sh
+++ b/src/tests.sh
@@ -1,8 +1,8 @@
#!/bin/sh
#
-# SOX Regression Test script.
+# SoX Regression Test script.
#
-# This script is just a quick sanity check of SOX on lossless format conversions.
+# This script is just a quick sanity check of SoX on lossless format conversions.
# verbose options
#verbose=-V
@@ -18,6 +18,7 @@
ub ) formatText="unsigned byte" ;;
uw ) formatText="unsigned word" ;;
raw) formatText="float"; formatFlags="-f -l" ;;
+ Raw) formatText="double"; formatFlags="-f -8" ;;
au ) formatFlags="-s" ;;
Wav) formatFlags="-u -b" ;;
esac
@@ -27,14 +28,14 @@
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
+ ./sox -c $channels -r $rate -n $format1Flags input.$format1 synth $samples's' sin 300-3300 noise
+ ./sox $verbose -r $rate -c $channels $format1Flags input.$format1 $format2Flags intermediate.$1
+ ./sox $verbose -r $rate -c $channels $format2Flags intermediate.$1 $format1Flags output.$format1
if cmp -s input.$format1 output.$format1
then
- echo "ok convert \"$format1Text\" <--> \"$format2Text\"."
+ echo "ok channels=$channels \"$format1Text\" <--> \"$format2Text\"."
else
- echo "*FAIL* convert \"$format1Text\" <--> \"$format2Text\"."
+ echo "*FAIL* channels=$channels \"$format1Text\" <--> \"$format2Text\"."
exit 1 # This allows failure inspection.
fi
rm -f input.$format1 intermediate.$1 output.$format1
@@ -42,31 +43,45 @@
done
}
-format1=ub
-rate=8012
-convertToAndFrom sb ub sw uw s3 u3 sl u4 raw dat au wav aiff aifc flac al
+do_multichannel_formats () {
+ format1=ub
+ convertToAndFrom sb ub sw uw s3 u3 sl u4 raw Raw dat au wav aiff aifc flac
-format1=sw
-convertToAndFrom sw uw s3 u3 sl u4 raw au wav aiff aifc flac ul
+ format1=sw
+ convertToAndFrom sw uw s3 u3 sl u4 raw Raw dat au wav aiff aifc flac
-format1=u3
-convertToAndFrom s3 u3 sl u4 wav flac
+ format1=u3
+ convertToAndFrom s3 u3 sl u4 raw Raw wav aiff aifc flac
-format1=sl
-convertToAndFrom sl u4 wav
+ format1=sl
+ convertToAndFrom sl u4 Raw wav
-format1=al
-convertToAndFrom al sw uw sl raw dat
+ format1=al
+ convertToAndFrom al sw uw sl raw Raw dat
-format1=ul
-convertToAndFrom ul sw uw sl raw dat
+ format1=ul
+ convertToAndFrom ul sw uw sl raw Raw dat
-format1=Wav
-convertToAndFrom Wav 8svx aiff aifc au avr dat maud sf smp
-rate=5512
-convertToAndFrom hcom
-rate=8000
-convertToAndFrom voc wve flac
+ format1=Wav
+ convertToAndFrom Wav aiff aifc au avr dat maud sf flac
+ samples=23492 convertToAndFrom 8svx # Even number of samples only
+ rate=8000 convertToAndFrom voc # Fixed rate
+
+ format1=wve
+ convertToAndFrom al sw uw sl raw Raw dat
+}
+
+do_singlechannel_formats () {
+ format1=Wav
+ convertToAndFrom smp
+ rate=5512 convertToAndFrom hcom # Fixed rate
+}
+
+rate=44100
+samples=23493
+channels=2 do_multichannel_formats
+channels=1 do_multichannel_formats
+channels=1 do_singlechannel_formats
./sox -c 1 -n output.ub synth .01 sine
if [ `wc -c <output.ub` = 441 ]; then
--- a/src/voc.c
+++ b/src/voc.c
@@ -481,10 +481,10 @@
v->samples += len;
while(done < len) {
if (ft->info.size == ST_SIZE_BYTE) {
- uc = ST_SAMPLE_TO_UNSIGNED_BYTE(*buf++);
+ uc = ST_SAMPLE_TO_UNSIGNED_BYTE(*buf++, ft->clippedCount);
st_writeb(ft, uc);
} else {
- sw = (int) ST_SAMPLE_TO_SIGNED_WORD(*buf++);
+ sw = (int) ST_SAMPLE_TO_SIGNED_WORD(*buf++, ft->clippedCount);
st_writew(ft,sw);
}
done++;
--- a/src/vox.c
+++ b/src/vox.c
@@ -275,7 +275,7 @@
short word;
while (count < length)
- { word = ST_SAMPLE_TO_SIGNED_WORD (*buffer++);
+ { word = ST_SAMPLE_TO_SIGNED_WORD (*buffer++, ft->clippedCount);
word /= 16;
byte <<= 4;
--- a/src/wav.c
+++ b/src/wav.c
@@ -349,7 +349,7 @@
while (done < len) {
while ((wav->gsmindex < 160*2) && (done < len))
wav->gsmsample[(wav->gsmindex)++] =
- ST_SAMPLE_TO_SIGNED_WORD(buf[done++]);
+ ST_SAMPLE_TO_SIGNED_WORD(buf[done++], ft->clippedCount);
if (wav->gsmindex < 160*2)
break;