shithub: sox

Download patch

ref: 2b1a302ecab9325dc84e1e6c91b45d5ff194978d
parent: fc5263cf0f108d31f5afda9007227c3afa03852b
author: cbagwell <cbagwell>
date: Fri Apr 13 17:13:52 EDT 2001

Adding intial support for 12-bit audio data inside sox.  AIFF files can
now read 12-bit audio data.

--- a/Changelog
+++ b/Changelog
@@ -47,6 +47,8 @@
     to use stderr.
   o Corrected AU header length value when comments were less than
     4 bytes.
+  o Added initial support for 12-bit audio data.  AIFF files can now read 12-bit audio
+    data but can not write it (lacks command line support).
 
 sox-12.17.1
 -----------
--- a/src/aiff.c
+++ b/src/aiff.c
@@ -246,15 +246,7 @@
 			st_readw(ft, &releaseLoopBegin);  /* begin marker */
 			st_readw(ft, &releaseLoopEnd);    /* end marker */
 
-			/* Required to ignore loops on playback if type
-			 * is 0 (NoLoop).  The other check is done for
-			 * historical reason and is probably not needed.
-			 */
-			if ((ft->loops[0].type == 0) ||
-			   (sustainLoopBegin == 0 && releaseLoopBegin == 0))
-				foundinstr = 0;
-			else
-				foundinstr = 1;
+			foundinstr = 1;
 		}
 		else if (strncmp(buf, "APPL", 4) == 0) {
 			st_readdw(ft, &chunksize);
@@ -375,6 +367,9 @@
 		case 8:
 			ft->info.size = ST_SIZE_BYTE;
 			break;
+		case 12:
+			ft->info.size = ST_SIZE_12BIT;
+			break;
 		case 16:
 			ft->info.size = ST_SIZE_WORD;
 			break;
@@ -403,7 +398,11 @@
 		st_fail_errno(ft,ST_EFMT,"Bogus AIFF file: MARKers but no INSTrument.");
 		return(ST_EOF);
 	}
-	if (!foundmark && foundinstr)
+	/* 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)
 	{
 		st_fail_errno(ft,ST_EFMT,"Bogus AIFF file: INSTrument but no MARKers.");
 		return(ST_EOF);
--- a/src/au.c
+++ b/src/au.c
@@ -402,6 +402,7 @@
 	ULONG sample_rate;
 	ULONG channels;
 	int   x;
+	int   comment_size;
 
 	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.");
@@ -422,9 +423,13 @@
 	if (ft->comment == NULL)
 		ft->comment = "SOX";
 
-	hdr_size = SUN_HDRSIZE + strlen(ft->comment) + 1; /*+1 = null-term. */
-	if (strlen(ft->comment) < 3)
-	    hdr_size += 3 - strlen(ft->comment);
+	hdr_size = SUN_HDRSIZE;
+
+	comment_size = strlen(ft->comment) + 1; /*+1 = null-term. */
+	if (comment_size < 4)
+	    comment_size = 4; /* minimum size */
+
+	hdr_size += comment_size;
 
 	st_writedw(ft, hdr_size);
 
--- a/src/misc.c
+++ b/src/misc.c
@@ -30,7 +30,8 @@
 	"longs",
 	"32-bit floats",
 	"64-bit floats",
-	"IEEE floats"
+	"IEEE floats",
+	"12-bit shorts"
 };
 
 const char *st_encodings_str[] = {
--- a/src/raw.c
+++ b/src/raw.c
@@ -43,16 +43,19 @@
 	switch(ft->info.size) {
 		case ST_SIZE_BYTE:
 			sample_size = 1;
-		break;
+		        break;
+		case ST_SIZE_12BIT:
+			sample_size = sizeof(short);
+			break;
 		case ST_SIZE_WORD:
 			sample_size = sizeof(short);
-		break;
+		        break;
 		case ST_SIZE_DWORD:
 			sample_size = sizeof(LONG);
-		break;
+		        break;
 		case ST_SIZE_FLOAT:
 			sample_size = sizeof(float);
-		break;
+		        break;
 		default:
 			st_fail_errno(ft,ST_ENOTSUP,"Can't seek this data size");
 			return(ft->st_errno);
@@ -172,6 +175,24 @@
 		swapn(p,n);
 }
 
+static int blockr_s12bit(p0, n, ft)
+LONG *p0,n;
+ft_t ft;
+{
+    LONG x, done;
+		short s;
+
+		for (done=0; done < n;) {
+			blockr(&s, sizeof(short), ft);
+			x = s;
+			if (ft->file.eof) break;
+			/* scale signed up to long's range */
+			*p0++ = LEFT(x, 20);
+			done++;
+		}
+	return done;
+}
+
 static int blockr_sw(p0, n, ft)
 LONG *p0,n;
 ft_t ft;
@@ -278,6 +299,35 @@
 				return 0;
 		    }
 		    break;
+		case ST_SIZE_12BIT:
+		    switch(ft->info.encoding)
+		    {
+			case ST_ENCODING_SIGN2:
+				return blockr_s12bit(buf, nsamp, ft);
+			case ST_ENCODING_UNSIGNED:
+				while(done < nsamp) {
+					LONG x;
+					unsigned short s;
+					blockr(&s, sizeof(short), ft);
+					x = s;
+					if (ft->file.eof)
+						return done;
+					/* Convert to signed */
+					x ^= 0x8000;
+					/* scale signed up to long's range */
+					*buf++ = LEFT(x, 20);
+					done++;
+				}
+				return done;
+			case ST_ENCODING_ULAW:
+				st_fail_errno(ft,ST_EFMT,"No U-Law support for shorts");
+				return 0;
+			case ST_ENCODING_ALAW:
+				st_fail_errno(ft,ST_EFMT,"No A-Law support for shorts");
+				return 0;
+		    }
+		    break;
+
 		case ST_SIZE_DWORD:
 		    switch(ft->info.encoding)
 		    {
--- a/src/st.h
+++ b/src/st.h
@@ -181,8 +181,9 @@
 #define	ST_SIZE_FLOAT	5
 #define ST_SIZE_DOUBLE	6
 #define ST_SIZE_IEEE	7	/* IEEE 80-bit floats. */
+#define ST_SIZE_12BIT   8
 
-#define ST_SIZE_MAX     7
+#define ST_SIZE_MAX     8
 
 /* Style field */
 #define ST_ENCODING_UNSIGNED	1 /* unsigned linear: Sound Blaster */
--- a/src/util.c
+++ b/src/util.c
@@ -436,7 +436,7 @@
 
 	if ((ft->info.size <= 0) || (ft->info.size > ST_SIZE_MAX))
 	{
-		st_fail_errno(ft,ST_EFMT,"Data size %i for %s file is bogus\n", ft->filename,ft->info.size);
+		st_fail_errno(ft,ST_EFMT,"Data size %i for %s file is bogus\n", ft->info.size, ft->filename);
 		return ST_EOF;
 	}
 
@@ -443,7 +443,7 @@
 	/* anyway to check length on st_encoding_str[] ? */ 
 	if (ft->info.encoding <= 0  || ft->info.encoding > ST_ENCODING_MAX)
 	{
-		st_fail_errno(ft,ST_EFMT,"Data encoding %i for %s file is bogus\n", ft->filename,ft->info.encoding);
+		st_fail_errno(ft,ST_EFMT,"Data encoding %i for %s file is bogus\n", ft->info.encoding, ft->filename);
 		return ST_EOF;
 	}