shithub: sox

Download patch

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);
 }
-
-