shithub: aacenc

Download patch

ref: d38a8eaff8114fabdecfcfb7d6256dc641ccfc3a
parent: 856aa84b8e53dea0c8ff91934f29a11368be9c1e
author: knik <knik>
date: Thu Jul 10 15:18:38 EDT 2003

24-bit input support.
Multichannel input remapping.
WAVEFORMATEXTENSIBLE support.

--- a/frontend/input.c
+++ b/frontend/input.c
@@ -16,7 +16,7 @@
  * License along with this library; if not, write to the Free Software
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  *
- * $Id: input.c,v 1.6 2003/06/21 08:58:27 knik Exp $
+ * $Id: input.c,v 1.7 2003/07/10 19:18:38 knik Exp $
  */
 
 #ifdef HAVE_CONFIG_H
@@ -25,15 +25,7 @@
 
 #include <stdio.h>
 #include <stdlib.h>
-#include <sys/types.h>
 
-#ifndef HAVE_U_INT32_T
-typedef unsigned int u_int32_t;
-#endif
-#ifndef HAVE_U_INT16_T
-typedef unsigned short u_int16_t;
-#endif
-
 #ifdef WIN32
 #include <fcntl.h>
 #endif
@@ -40,10 +32,13 @@
 
 #include "input.h"
 
-#ifdef WORDS_BIGENDIAN
-# define UINT32(x) (((x & 0xff) << 24) | ((x & 0xff00) << 8) \
+#define SWAP32(x) (((x & 0xff) << 24) | ((x & 0xff00) << 8) \
 	| ((x & 0xff0000) >> 8) | ((x & 0xff000000) >> 24))
-# define UINT16(x) (((x & 0xff) << 8) | ((x & 0xff00) >> 8))
+#define SWAP16(x) (((x & 0xff) << 8) | ((x & 0xff00) >> 8))
+
+#ifdef WORDS_BIGENDIAN
+# define UINT32(x) SWAP32(x)
+# define UINT16(x) SWAP16(x)
 #else
 # define UINT32(x) (x)
 # define UINT16(x) (x)
@@ -64,7 +59,8 @@
 }
 riffsub_t;
 
-#define WAVE_FORMAT_PCM 1
+#define WAVE_FORMAT_PCM		1
+#define WAVE_FORMAT_EXTENSIBLE	0xfffe
 typedef struct
 {
   u_int16_t wFormatTag;
@@ -77,15 +73,39 @@
 }
 WAVEFORMATEX;
 
-pcmfile_t *wav_open_read(const char *name,
-			 int rawchans, int rawbits, int rawrate)
+typedef struct
 {
+  WAVEFORMATEX Format;
+  union {
+    u_int16_t wValidBitsPerSample;	// bits of precision
+    u_int16_t wSamplesPerBlock;		// valid if wBitsPerSample==0
+    u_int16_t wReserved;		// If neither applies, set to zero.
+  } Samples;
+  u_int32_t dwChannelMask;		// which channels are present in stream
+  unsigned char SubFormat[16];		// guid
+} WAVEFORMATEXTENSIBLE;
+
+static unsigned char waveformat_pcm_guid[16] =
+{
+  WAVE_FORMAT_PCM,0,0,0,
+  0x00, 0x00,
+  0x10, 0x00,
+  0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71
+};
+
+static void unsuperr(const char *name)
+{
+  fprintf(stderr, "%s: file format not supported\n", name);
+}
+
+pcmfile_t *wav_open_read(const char *name, int rawinput)
+{
   int i;
   int skip;
   FILE *wave_f;
   riff_t riff;
   riffsub_t riffsub;
-  WAVEFORMATEX wave;
+  WAVEFORMATEXTENSIBLE wave;
   char *riffl = "RIFF";
   char *wavel = "WAVE";
   char *fmtl = "fmt ";
@@ -108,60 +128,73 @@
     return NULL;
   }
 
-  if (rawchans < 1) // header input
+  if (!rawinput) // header input
   {
-  if (fread(&riff, 1, sizeof(riff), wave_f) != sizeof(riff))
-    return NULL;
-  if (memcmp(&(riff.label), riffl, 4))
-    return NULL;
-  if (memcmp(&(riff.chunk_type), wavel, 4))
-    return NULL;
+    if (fread(&riff, 1, sizeof(riff), wave_f) != sizeof(riff))
+      return NULL;
+    if (memcmp(&(riff.label), riffl, 4))
+      return NULL;
+    if (memcmp(&(riff.chunk_type), wavel, 4))
+      return NULL;
 
-  if (fread(&riffsub, 1, sizeof(riffsub), wave_f) != sizeof(riffsub))
-    return NULL;
-  riffsub.len = UINT32(riffsub.len);
-  if (memcmp(&(riffsub.label), fmtl, 4))
-    return NULL;
-  memset(&wave, 0, sizeof(wave));
-  fmtsize = (riffsub.len < sizeof(wave)) ? riffsub.len : sizeof(wave);
-  if (fread(&wave, 1, fmtsize, wave_f) != fmtsize)
-    return NULL;
-
-  for (skip = riffsub.len - fmtsize; skip > 0; skip--)
-    fgetc(wave_f);
-
-  for (i = 0;; i++)
-  {
     if (fread(&riffsub, 1, sizeof(riffsub), wave_f) != sizeof(riffsub))
       return NULL;
     riffsub.len = UINT32(riffsub.len);
-    if (!memcmp(&(riffsub.label), datal, 4))
-      break;
-    if (i > 10)
+    if (memcmp(&(riffsub.label), fmtl, 4))
       return NULL;
+    memset(&wave, 0, sizeof(wave));
+    fmtsize = (riffsub.len < sizeof(wave)) ? riffsub.len : sizeof(wave);
+    if (fread(&wave, 1, fmtsize, wave_f) != fmtsize)
+      return NULL;
 
-    for (skip = riffsub.len; skip > 0; skip--)
+    for (skip = riffsub.len - fmtsize; skip > 0; skip--)
       fgetc(wave_f);
+
+    for (i = 0;; i++)
+    {
+      if (fread(&riffsub, 1, sizeof(riffsub), wave_f) != sizeof(riffsub))
+	return NULL;
+      riffsub.len = UINT32(riffsub.len);
+      if (!memcmp(&(riffsub.label), datal, 4))
+	break;
+      if (i > 10)
+	return NULL;
+
+      for (skip = riffsub.len; skip > 0; skip--)
+	fgetc(wave_f);
+    }
+    if (UINT16(wave.Format.wFormatTag) != WAVE_FORMAT_PCM)
+    {
+      if (UINT16(wave.Format.wFormatTag) == WAVE_FORMAT_EXTENSIBLE)
+      {
+	if (UINT16(wave.Format.cbSize) < 22) // struct too small
+	  return NULL;
+	if (memcmp(wave.SubFormat, waveformat_pcm_guid, 16))
+	{
+          unsuperr(name);
+	  return NULL;
+	}
+      }
+      else
+      {
+	unsuperr(name);
+	return NULL;
+      }
+    }
   }
-  if (UINT16(wave.wFormatTag) != WAVE_FORMAT_PCM)
-    return NULL;
-  }
 
   sndf = malloc(sizeof(*sndf));
+  memset(sndf, 0, sizeof(*sndf));
   sndf->f = wave_f;
-  if (rawchans > 0) // raw input
+  if (rawinput)
   {
     sndf->bigendian = 1;
-    sndf->channels = rawchans;
-    sndf->samplebits = rawbits;
-    sndf->samplerate = rawrate;
     if (dostdin)
       sndf->samples = 0;
     else
     {
       fseek(sndf->f, 0 , SEEK_END);
-      sndf->samples = ftell(sndf->f) /
-	(((sndf->samplebits > 8) ? 2 : 1) * sndf->channels);
+      sndf->samples = ftell(sndf->f) / (sndf->samplebytes * sndf->channels);
       rewind(sndf->f);
     }
   }
@@ -168,42 +201,132 @@
   else
   {
     sndf->bigendian = 0;
-  sndf->channels = UINT16(wave.nChannels);
-  sndf->samplebits = UINT16(wave.wBitsPerSample);
-  sndf->samplerate = UINT32(wave.nSamplesPerSec);
-  sndf->samples = riffsub.len /
-    (((UINT16(wave.wBitsPerSample) > 8) ? 2 : 1) * sndf->channels);
+    sndf->channels = UINT16(wave.Format.nChannels);
+    sndf->samplebytes = UINT16(wave.Format.wBitsPerSample) / 8;
+    sndf->samplerate = UINT32(wave.Format.nSamplesPerSec);
+    sndf->samples = riffsub.len / (sndf->samplebytes * sndf->channels);
   }
   return sndf;
 }
 
-size_t wav_read_short(pcmfile_t *sndf, short *buf, size_t num)
+
+static void chan_remap(int32_t *buf, int channels, int blocks, int *map)
 {
+  int i;
+  int32_t *tmp = alloca(channels * sizeof(int32_t));
+
+  for (i = 0; i < blocks; i++)
+  {
+    int chn;
+
+    memcpy(tmp, buf + i * channels, sizeof(int32_t) * channels);
+
+    for (chn = 0; chn < channels; chn++)
+      buf[i * channels + chn] = tmp[map[chn]];
+  }
+}
+
+size_t wav_read_int24(pcmfile_t *sndf, int32_t *buf, size_t num, int *map)
+{
   int size;
   int i;
+  unsigned char *bufi;
 
-  if (sndf->samplebits > 8) {
-    size = fread(buf, 2, num, sndf->f);
-    // fix endianness
+  if ((sndf->samplebytes > 4) || (sndf->samplebytes < 1))
+    return 0;
+
+  bufi = (char *)buf + sizeof(*buf) * num - sndf->samplebytes * (num - 1) - sizeof(*buf);
+
+  size = fread(bufi, sndf->samplebytes, num, sndf->f);
+
+  // convert to 24 bit
+  // fix endianness
+  switch (sndf->samplebytes) {
+  case 1:
+    /* this is endian clean */
+    for (i = 0; i < size; i++)
+      buf[i] = (bufi[i] - 128) * 65536;
+    break;
+
+  case 2:
 #ifdef WORDS_BIGENDIAN
     if (!sndf->bigendian)
 #else
     if (sndf->bigendian)
 #endif
+    {
       // swap bytes
       for (i = 0; i < size; i++)
       {
+	int16_t s = ((int16_t *)bufi)[i];
+
+	s = SWAP16(s);
+
+	buf[i] = ((uint32_t)s) << 8;
+      }
+    }
+    else
+    {
+      // no swap
+      for (i = 0; i < size; i++)
+      {
+	int s = ((int16_t *)bufi)[i];
+
+	buf[i] = s << 8;
+      }
+    }
+    break;
+
+  case 3:
+    if (!sndf->bigendian)
+    {
+      for (i = 0; i < size; i++)
+      {
+	int s = bufi[3 * i] | (bufi[3 * i + 1] << 8) | (bufi[3 * i + 2] << 16);
+
+        // fix sign
+	if (s & 0x800000)
+          s |= 0xff000000;
+
+	buf[i] = s;
+      }
+    }
+    else // big endian input
+    {
+      for (i = 0; i < size; i++)
+      {
+	int s = (bufi[3 * i] << 16) | (bufi[3 * i + 1] << 8) | bufi[3 * i + 2];
+
+        // fix sign
+	if (s & 0x800000)
+          s |= 0xff000000;
+
+	buf[i] = s;
+      }
+    }
+    break;
+
+  case 4:
+#ifdef WORDS_BIGENDIAN
+    if (!sndf->bigendian)
+#else
+    if (sndf->bigendian)
+#endif
+    {
+      // swap bytes
+      for (i = 0; i < size; i++)
+      {
 	int s = buf[i];
-	buf[i] = ((s & 0xff) << 8) | ((s & 0xff00) >> 8);
+
+	buf[i] = SWAP32(s);
+      }
     }
-    return size;
+    break;
   }
 
-  /* this is endian clean */
-  // convert to 16 bit
-  size = fread(buf, 1, num, sndf->f);
-  for (i = size - 1; i >= 0; i--)
-    buf[i] = (((char *)buf)[i] - 128) * 256;
+  if (map)
+    chan_remap(buf, sndf->channels, size / sndf->channels, map);
+
   return size;
 }