ref: 6ed1e47dc50f0042e9045225487d0b07ebe410cd
parent: 64ec5ace8d13790782adc96a723752fd05bc0b88
author: cbagwell <cbagwell>
date: Fri May 4 11:09:59 EDT 2001
Bug fix in au.c for ALAW sizes. Change AIFF to ignore unmatched MARK/INSTR chunks. Added updated version of unsupported silence effect.
--- a/Changelog
+++ b/Changelog
@@ -48,6 +48,8 @@
o Corrected AU header length value when comments were less than
4 bytes.
o Added support for reading non-standard bit size data from AIFF files.
+ o Ignore unmatched MARK/INSTR chunks in AIFF files now instead of quiting.
+ o Fixed ALAW encoding bug in .au files as pointed out by Bruce Forsberg.
sox-12.17.1
-----------
--- a/src/8svx.c
+++ b/src/8svx.c
@@ -177,6 +177,7 @@
}
st_readdw(ft, &(p->nsamples));
+ ft->length = p->nsamples;
ft->info.channels = channels;
ft->info.rate = rate;
ft->info.encoding = ST_ENCODING_SIGN2;
--- a/src/aiff.c
+++ b/src/aiff.c
@@ -403,17 +403,13 @@
if (foundmark && !foundinstr)
{
- st_fail_errno(ft,ST_EFMT,"Bogus AIFF file: MARKers but no INSTrument.");
- return(ST_EOF);
+ st_report("Ignoring MARK chunk since no INSTR found.");
+ foundmark = 0;
}
- /* Check for INST chunk found but no MARK chunk. One case that is OK is
- * if the INST chunk is of type NOLOOP which means its not much of an instrument
- * anyways.
- */
- if (!foundmark && foundinstr && ft->loops[0].type != 0)
+ if (!foundmark && foundinstr)
{
- st_fail_errno(ft,ST_EFMT,"Bogus AIFF file: INSTrument but no MARKers.");
- return(ST_EOF);
+ st_report("Ignoring INSTR chunk since no MARK found.");
+ foundinstr = 0;
}
if (foundmark && foundinstr) {
int i;
--- a/src/au.c
+++ b/src/au.c
@@ -72,7 +72,8 @@
break;
case SUN_ALAW:
*encoding = ST_ENCODING_ALAW;
- *size = ST_SIZE_BYTE;
+ *size = ST_SIZE_BYTE;
+ break;
case SUN_LIN_8:
*encoding = ST_ENCODING_SIGN2;
*size = ST_SIZE_BYTE;
--- a/src/silence.c
+++ b/src/silence.c
@@ -1,119 +1,163 @@
-/*
- * silence - effect to detect periods of silence in audio data and
- * use this to clip data before and after.
- *
- * Written by Chris Bagwell (cbagwell@sprynet.com) - January 10, 1999
- *
- * Copyright 1999 Chris Bagwell And Sundry Contributors
- * This source code is freely redistributable and may be used for
- * any purpose. This copyright notice must be maintained.
- * Chris Bagwell And Sundry Contributors are not responsible for
- * the consequences of using this software.
- */
+// Silence effect for SoX
+// by Heikki Leinonen (heilei@iki.fi) 25.03.2001
+//
+// This effect deletes samples from the start of the sound
+// file until a sample exceeds a given threshold (either
+// left or right channel in stereo files). This can be used
+// to filter out unwanted silence or low noise in the beginning
+// of a sound file. The threshold can be given either as a
+// percentage or in decibels.
+
+#include <math.h>
#include "st.h"
-/* Private data for SKEL file */
-typedef struct silencestuff {
- int threshold;
- int threshold_length;
- int threshold_count;
- int begin;
- int begin_skip;
- int begin_count;
- int end;
- int end_skip;
- int end_count;
-} *silenc_t;
+#ifndef min
+ #define min(s1,s2) ((s1)<(s2)?(s1):(s2))
+#endif
-/*
- * Process options
- *
- * Don't do initialization now.
- * The 'info' fields are not yet filled in.
- */
-int st_silence_getopts(effp, n, argv)
-eff_t effp;
-int n;
-char **argv;
+#ifndef true
+ #define true 1
+#endif
+
+#ifndef false
+ #define false 0
+#endif
+
+// Private data for silence effect.
+
+#define DEFAULT_THRESHOLD 1.0
+#define DEFAULT_UNIT '%'
+
+typedef struct silencestuff
{
- if (n)
+ double threshold;
+ char unit; // "d" for decibels or "%" for percent.
+ int wentAboveThreshold;
+} *silence_t;
+
+
+int st_silence_getopts(eff_t effp, int n, char **argv)
+{
+ silence_t silence = (silence_t) effp->priv;
+
+ silence->threshold = DEFAULT_THRESHOLD;
+ silence->unit = DEFAULT_UNIT;
+ switch (n)
{
- st_fail("Silence effect takes no options.");
- return (ST_EOF);
+ case 0: // No arguments, use defaults given above.
+ break;
+
+ case 1:
+ sscanf(argv[0], "%lf", &silence->threshold);
+ break;
+
+ default:
+ sscanf(argv[0], "%lf", &silence->threshold);
+ sscanf(argv[1], "%c", &silence->unit);
+ break;
}
+ if ((silence->unit != '%') && (silence->unit != 'd'))
+ st_fail("Usage: silence [threshold [d | %%]]");
+ if ((silence->unit == '%') && ((silence->threshold < 0.0) || (silence->threshold > 100.0)))
+ st_fail("silence threshold should be between 0.0 and 100.0 %%");
+ if ((silence->unit == 'd') && (silence->threshold >= 0.0))
+ st_fail("silence threshold should be less than 0.0 dB");
+ return(ST_SUCCESS);
}
-/*
- * Prepare processing.
- * Do all initializations.
- */
-int st_silence_start(effp)
-eff_t effp;
+int st_silence_start(eff_t effp)
{
- silence_t silence = (silence_t) effp->priv;
+ silence_t silence = (silence_t) effp->priv;
- silence.threshold = 5;
- silence.thres_length = 1000;
- silence.thres_count = 0;
+ silence->wentAboveThreshold = false;
- silence.begin = silence.end = 0;
- silence.begin_skip = silence.end_skip = 0;
- silence.begin_count = silence.end_count = 0;
- return (ST_SUCCESS);
+ if ((effp->outinfo.channels != 1) && (effp->outinfo.channels != 2))
+ {
+ st_fail("Silence effect can only be run on mono or stereo data");
+ return (ST_EOF);
+ }
+ return(ST_SUCCESS);
}
-/*
- * Processed signed long samples from ibuf to obuf.
- * Return number of samples processed.
- */
+int aboveThreshold(LONG value, double threshold, char unit)
+{
+ double maxLong = 2147483647.0;
+ double ratio, percentRatio, decibelRatio;
-int st_silence_flow(effp, ibuf, obuf, isamp, osamp)
-eff_t effp;
-LONG *ibuf, *obuf;
-LONG *isamp, *osamp;
+ ratio = (double) labs(value) / maxLong;
+ percentRatio = ratio * 100.0;
+ decibelRatio = log10(ratio) * 20.0;
+ return((unit == '%') ? (percentRatio >= threshold) : (decibelRatio >= threshold));
+}
+
+// Process signed long samples from ibuf to obuf.
+// Return number of samples processed in isamp and osamp.
+int st_silence_flow(eff_t effp, LONG *ibuf, LONG *obuf, LONG *isamp, LONG *osamp)
{
- silence_t silence = (silence_t) effp->priv;
- int len, done;
-
- len = ((*isamp > *osamp) ? *osamp : *isamp);
- for(done = 0; done < len; done++) {
- if (silence.threshold_count >= silence.threshold_length) {
-
-
- if no more samples
- break
- get a sample
- l = sample converted to signed long
- *buf++ = l;
+ silence_t silence = (silence_t) effp->priv;
+ int nrOfTicks, i;
+ LONG leftSample, rightSample, monoSample, nrOfInSamplesRead, nrOfOutSamplesWritten;
+
+ nrOfInSamplesRead = 0;
+ nrOfOutSamplesWritten = 0;
+
+ switch (effp->outinfo.channels)
+ {
+ case 1:
+ nrOfTicks = min((*isamp), (*osamp));
+ for(i = 0; i < nrOfTicks; i++)
+ {
+ monoSample = ibuf[0];
+ if (silence->wentAboveThreshold || aboveThreshold(monoSample, silence->threshold, silence->unit))
+ {
+ silence->wentAboveThreshold = true;
+ obuf[0] = ibuf[0]; // Copy data from input to output.
+ obuf++; // Advance output buffers by 1 sample.
+ nrOfOutSamplesWritten++;
+ }
+ ibuf++; // Always advance input buffers by 1 sample.
+ nrOfInSamplesRead++;
+ }
+ break;
+
+ case 2:
+ nrOfTicks = min((*isamp), (*osamp)) / 2;
+ for(i = 0; i < nrOfTicks; i++)
+ {
+ leftSample = ibuf[0];
+ rightSample = ibuf[1];
+ if (silence->wentAboveThreshold || aboveThreshold(leftSample, silence->threshold, silence->unit) || aboveThreshold(rightSample, silence->threshold, silence->unit))
+ {
+ silence->wentAboveThreshold = true;
+ obuf[0] = ibuf[0]; // Copy data from input to output.
+ obuf[1] = ibuf[1];
+ obuf += 2; // Advance output buffers by 2 samples.
+ nrOfOutSamplesWritten += 2;
+ }
+ ibuf += 2; // Always advance input buffers by 2 samples.
+ nrOfInSamplesRead += 2;
+ }
+ break;
+
+ default: // We should never get here, but just in case...
+ st_fail("Silence effect can only be run on mono or stereo data");
+ break;
}
- *isamp =
- *osamp =
+ *isamp = nrOfInSamplesRead;
+ *osamp = nrOfOutSamplesWritten;
+
return (ST_SUCCESS);
}
-/*
- * Drain out remaining samples if the effect generates any.
- */
-
-int st_skel_drain(effp, obuf, osamp)
-LONG *obuf;
-LONG *osamp;
+int st_silence_drain(eff_t effp, LONG *obuf, LONG *osamp)
{
*osamp = 0;
- return (ST_SUCCESS);
+ return(ST_SUCCESS);
}
-/*
- * Do anything required when you stop reading samples.
- * (free allocated memory, etc.)
- */
-int st_skel_stop(effp)
-eff_t effp;
+int st_silence_stop(eff_t effp)
{
- /* nothing to do */
- return (ST_SUCCESS);
+ return(ST_SUCCESS);
}
-
-