shithub: aacdec

Download patch

ref: e98a69b9db88ef00994bbc7a95add426a36adcf6
parent: 9831e451d4dffcfe05f7d8d60e3c96c8f04d7eef
author: menno <menno>
date: Mon Jul 7 17:11:18 EDT 2003

Added file playback (WIN32) with priority setting
Coupling channels are now skipped
Minor updates in frontend
ADIF bugfix
Small fixes

--- a/aacDECdrop/decode.c
+++ b/aacDECdrop/decode.c
@@ -16,8 +16,8 @@
 ** along with this program; if not, write to the Free Software
 ** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 **
-** $Id: decode.c,v 1.13 2003/05/07 18:30:48 menno Exp $
-** $Id: decode.c,v 1.13 2003/05/07 18:30:48 menno Exp $
+** $Id: decode.c,v 1.14 2003/07/07 21:11:17 menno Exp $
+** $Id: decode.c,v 1.14 2003/07/07 21:11:17 menno Exp $
 **/
 
 #ifdef _WIN32
@@ -42,7 +42,7 @@
 #define min(a,b) ( (a) < (b) ? (a) : (b) )
 #endif
 
-#define MAX_CHANNELS 6 /* make this higher to support files with
+#define MAX_CHANNELS 8 /* make this higher to support files with
                           more channels */
 
 /* FAAD file buffering routines */
--- a/common/mp4v2/Makefile.am
+++ b/common/mp4v2/Makefile.am
@@ -16,13 +16,18 @@
     atom_drep.cpp \
     atom_edts.cpp \
     atom_elst.cpp \
+    atom_enca.cpp \
+    atom_encv.cpp \
     atom_esds.cpp \
     atom_free.cpp \
+    atom_frma.cpp \
     atom_ftyp.cpp \
     atom_hdlr.cpp \
     atom_hinf.cpp \
     atom_hmhd.cpp \
     atom_hnti.cpp \
+    atom_iKMS.cpp \
+    atom_iSFM.cpp \
     atom_iods.cpp \
     atom_maxr.cpp \
     atom_mdat.cpp \
@@ -44,7 +49,10 @@
     atom_pmax.cpp \
     atom_root.cpp \
     atom_rtp.cpp \
+    atom_schi.cpp \
+    atom_schm.cpp \
     atom_sdp.cpp \
+    atom_sinf.cpp \
     atoms.h \
     atom_smhd.cpp \
     atom_snro.cpp \
@@ -57,7 +65,6 @@
     atom_stss.cpp \
     atom_stsz.cpp \
     atom_stts.cpp \
-    atom_tag4.cpp \
     atom_tfhd.cpp \
     atom_tims.cpp \
     atom_tkhd.cpp \
--- a/frontend/audio.c
+++ b/frontend/audio.c
@@ -16,7 +16,7 @@
 ** along with this program; if not, write to the Free Software
 ** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 **
-** $Id: audio.c,v 1.12 2003/02/27 11:37:26 menno Exp $
+** $Id: audio.c,v 1.13 2003/07/07 21:11:17 menno Exp $
 **/
 
 #ifdef _WIN32
@@ -63,13 +63,17 @@
         return NULL;
     }
 
-#ifdef _WIN32
-    if(infile[0] == '-')
+    if(!infile)
     {
+#ifdef __BORLANDC__
         setmode(fileno(stdout), O_BINARY);
-    }
+#elif defined _MSC_VER || defined __MINGW32__
+        _setmode(_fileno(stdout), _O_BINARY);
 #endif
-    aufile->sndfile = fopen(infile, "wb");
+        aufile->sndfile = stdout;
+    } else {
+        aufile->sndfile = fopen(infile, "wb");
+    }
 
     if (aufile->sndfile == NULL)
     {
@@ -80,6 +84,7 @@
     if (aufile->fileType == OUTPUT_WAV)
     {
         write_wav_header(aufile);
+        aufile->total_samples = 0;
     }
 
     return aufile;
@@ -108,17 +113,16 @@
     return 0;
 }
 
-void close_audio_file(audio_file *aufile)
+void close_audio_file(audio_file *aufile, char *fileName)
 {
-    if (aufile->fileType == OUTPUT_WAV)
+    if (aufile->fileType == OUTPUT_WAV && fileName)
     {
         fseek(aufile->sndfile, 0, SEEK_SET);
 
         write_wav_header(aufile);
+        fclose(aufile->sndfile);
     }
 
-    fclose(aufile->sndfile);
-
     if (aufile) free(aufile);
 }
 
@@ -127,8 +131,13 @@
     unsigned char header[44];
     unsigned char* p = header;
     unsigned int bytes = (aufile->bits_per_sample + 7) / 8;
-    float data_size = (float)bytes * aufile->total_samples;
+    float data_size;
     unsigned long word32;
+
+    if (aufile->total_samples)
+        data_size  = aufile->total_samples * bytes;
+    else
+        data_size = (float)(long)(0x7fffffff);
 
     *p++ = 'R'; *p++ = 'I'; *p++ = 'F'; *p++ = 'F';
 
--- a/frontend/audio.h
+++ b/frontend/audio.h
@@ -16,7 +16,7 @@
 ** along with this program; if not, write to the Free Software
 ** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 **
-** $Id: audio.h,v 1.5 2002/09/08 18:14:36 menno Exp $
+** $Id: audio.h,v 1.6 2003/07/07 21:11:17 menno Exp $
 **/
 
 #ifndef AUDIO_H_INCLUDED
@@ -45,7 +45,7 @@
 audio_file *open_audio_file(char *infile, int samplerate, int channels,
                             int outputFormat, int fileType);
 int write_audio_file(audio_file *aufile, void *sample_buffer, int samples);
-void close_audio_file(audio_file *aufile);
+void close_audio_file(audio_file *aufile, char *fileName);
 static int write_wav_header(audio_file *aufile);
 static int write_audio_16bit(audio_file *aufile, void *sample_buffer,
                              unsigned int samples);
--- a/frontend/faad.dsp
+++ b/frontend/faad.dsp
@@ -50,7 +50,7 @@
 # ADD BSC32 /nologo
 LINK32=xilink6.exe
 # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
-# ADD LINK32 ws2_32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /profile /machine:I386
+# ADD LINK32 ws2_32.lib winmm.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /profile /machine:I386
 
 !ELSEIF  "$(CFG)" == "faad - Win32 Debug"
 
@@ -74,7 +74,7 @@
 # ADD BSC32 /nologo
 LINK32=xilink6.exe
 # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
-# ADD LINK32 ws2_32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
+# ADD LINK32 ws2_32.lib winmm.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
 
 !ENDIF 
 
@@ -97,6 +97,10 @@
 
 SOURCE=.\main.c
 # End Source File
+# Begin Source File
+
+SOURCE=.\wave_out.c
+# End Source File
 # End Group
 # Begin Group "Header Files"
 
@@ -124,6 +128,10 @@
 # Begin Source File
 
 SOURCE=..\common\mp4v2\systems.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\wave_out.h
 # End Source File
 # Begin Source File
 
--- a/frontend/main.c
+++ b/frontend/main.c
@@ -16,7 +16,7 @@
 ** along with this program; if not, write to the Free Software
 ** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 **
-** $Id: main.c,v 1.36 2003/07/07 09:48:31 menno Exp $
+** $Id: main.c,v 1.37 2003/07/07 21:11:17 menno Exp $
 **/
 
 #ifdef _WIN32
@@ -34,14 +34,17 @@
 #include <mp4.h>
 
 #include "audio.h"
+#ifdef _WIN32
+#include "wave_out.h"
+#endif
 
 #ifndef min
 #define min(a,b) ( (a) < (b) ? (a) : (b) )
 #endif
 
-#define MAX_CHANNELS 6 /* make this higher to support files with
-
+#define MAX_CHANNELS 8 /* make this higher to support files with
                           more channels */
+
 /* FAAD file buffering routines */
 typedef struct {
     long bytes_into_buffer;
@@ -172,43 +175,51 @@
 
 void usage(void)
 {
-    fprintf(stderr, "\nUsage:\n");
-    fprintf(stderr, "%s [options] infile.aac\n", progName);
-    fprintf(stderr, "Options:\n");
-    fprintf(stderr, " -h    Shows this help screen.\n");
-    fprintf(stderr, " -i    Shows info about the input file.\n");
-    fprintf(stderr, " -o X  Set output filename.\n");
-    fprintf(stderr, " -f X  Set output format. Valid values for X are:\n");
-    fprintf(stderr, "        1:  Microsoft WAV format (default).\n");
-    fprintf(stderr, "        2:  RAW PCM data.\n");
-    fprintf(stderr, " -b X  Set output sample format. Valid values for X are:\n");
-    fprintf(stderr, "        1:  16 bit PCM data (default).\n");
-    fprintf(stderr, "        2:  24 bit PCM data.\n");
-    fprintf(stderr, "        3:  32 bit PCM data.\n");
-    fprintf(stderr, "        4:  32 bit floating point data.\n");
-    fprintf(stderr, "        5:  64 bit floating point data.\n");
-    fprintf(stderr, "        6:  16 bit PCM data (dithered).\n");
-    fprintf(stderr, "        7:  16 bit PCM data (dithered with LIGHT noise shaping).\n");
-    fprintf(stderr, "        8:  16 bit PCM data (dithered with MEDIUM noise shaping).\n");
-    fprintf(stderr, "        9:  16 bit PCM data (dithered with HEAVY noise shaping).\n");
-    fprintf(stderr, " -s X  Force the samplerate to X (for RAW files).\n");
-    fprintf(stderr, " -l X  Set object type. Supported object types:\n");
-    fprintf(stderr, "        0:  Main object type.\n");
-    fprintf(stderr, "        1:  LC (Low Complexity) object type.\n");
-    fprintf(stderr, "        3:  LTP (Long Term Prediction) object type.\n");
-    fprintf(stderr, "        23: LD (Low Delay) object type.\n");
-    fprintf(stderr, " -w    Write output to stdio instead of a file.\n");
-    fprintf(stderr, "Example:\n");
-    fprintf(stderr, "       faad infile.aac\n");
-    fprintf(stderr, "       faad infile.mp4\n");
-    fprintf(stderr, "       faad -o outfile.wav infile.aac\n");
-    fprintf(stderr, "       faad -w infile.aac > outfile.wav\n");
+    fprintf(stdout, "\nUsage:\n");
+    fprintf(stdout, "%s [options] infile.aac\n", progName);
+    fprintf(stdout, "Options:\n");
+    fprintf(stdout, " -h    Shows this help screen.\n");
+    fprintf(stdout, " -i    Shows info about the input file.\n");
+    fprintf(stdout, " -o X  Set output filename.\n");
+    fprintf(stdout, " -f X  Set output format. Valid values for X are:\n");
+    fprintf(stdout, "        1:  Microsoft WAV format (default).\n");
+    fprintf(stdout, "        2:  RAW PCM data.\n");
+    fprintf(stdout, " -b X  Set output sample format. Valid values for X are:\n");
+    fprintf(stdout, "        1:  16 bit PCM data (default).\n");
+    fprintf(stdout, "        2:  24 bit PCM data.\n");
+    fprintf(stdout, "        3:  32 bit PCM data.\n");
+    fprintf(stdout, "        4:  32 bit floating point data.\n");
+    fprintf(stdout, "        5:  64 bit floating point data.\n");
+    fprintf(stdout, "        6:  16 bit PCM data (dithered).\n");
+    fprintf(stdout, "        7:  16 bit PCM data (dithered with LIGHT noise shaping).\n");
+    fprintf(stdout, "        8:  16 bit PCM data (dithered with MEDIUM noise shaping).\n");
+    fprintf(stdout, "        9:  16 bit PCM data (dithered with HEAVY noise shaping).\n");
+    fprintf(stdout, " -s X  Force the samplerate to X (for RAW files).\n");
+    fprintf(stdout, " -l X  Set object type. Supported object types:\n");
+    fprintf(stdout, "        0:  Main object type.\n");
+    fprintf(stdout, "        1:  LC (Low Complexity) object type.\n");
+    fprintf(stdout, "        3:  LTP (Long Term Prediction) object type.\n");
+    fprintf(stdout, "        23: LD (Low Delay) object type.\n");
+    fprintf(stdout, " -w    Write output to stdio instead of a file.\n");
+#ifdef _WIN32
+    fprintf(stdout, " -p    Plays aac/mp4 files thru the soundcard using Windows audio.\n");
+    fprintf(stdout, " Playback Priority Options (ONE option ONLY may be used)\n");
+    fprintf(stdout, " -c X  Set playback priority class, where X =\n");
+    fprintf(stdout, "        0:  NORMAL priority.\n");
+    fprintf(stdout, "        1:  HIGH priority (default).\n");
+    fprintf(stdout, "        2:  REALTIME priority.\n");
+#endif
+    fprintf(stdout, "Example:\n");
+    fprintf(stdout, "       faad infile.aac\n");
+    fprintf(stdout, "       faad infile.mp4\n");
+    fprintf(stdout, "       faad -o outfile.wav infile.aac\n");
+    fprintf(stdout, "       faad -w infile.aac > outfile.wav\n");
     return;
 }
 
 int decodeAACfile(char *aacfile, char *sndfile, int to_stdout,
                   int def_srate, int object_type, int outputFormat, int fileType,
-                  int infoOnly)
+                  int infoOnly, int playback, unsigned int play_priority)
 {
     int tagsize;
     unsigned long samplerate;
@@ -336,7 +347,7 @@
     fill_buffer(&b);
 
     /* print AAC file info */
-    fprintf(stderr, "AAC file info:\n");
+    fprintf(stderr, "%s file info:\n", aacfile);
     switch (header_type)
     {
     case 0:
@@ -356,8 +367,6 @@
     {
         faacDecClose(hDecoder);
         fclose(b.infile);
-        if (!first_time)
-            close_audio_file(aufile);
         if (b.buffer)
             free(b.buffer);
         return 0;
@@ -391,28 +400,49 @@
         /* open the sound file now that the number of channels are known */
         if (first_time && !frameInfo.error)
         {
-            if (!to_stdout)
+            if(to_stdout)
+                sndfile = NULL;
+
+            if(playback == 1)
             {
+#ifdef _WIN32
+                if (Set_WIN_Params(INVALID_FILEDESC, samplerate, SAMPLE_SIZE,
+                    frameInfo.channels, play_priority) < 0)
+                {
+                    fprintf(stderr, "ERROR: Can't access %s\n", "WAVE OUT");
+                    if (b.buffer)
+                        free(b.buffer);
+                    faacDecClose(hDecoder);
+                    fclose(b.infile);
+                    return 0;
+                }
+#endif
+            } else {
                 aufile = open_audio_file(sndfile, frameInfo.samplerate, frameInfo.channels,
                     outputFormat, fileType);
-            } else {
-                aufile = open_audio_file("-", frameInfo.samplerate, frameInfo.channels,
-                    outputFormat, fileType);
+
+                if (aufile == NULL)
+                {
+                    if (b.buffer)
+                        free(b.buffer);
+                    faacDecClose(hDecoder);
+                    fclose(b.infile);
+                    return 0;
+                }
             }
-            if (aufile == NULL)
-            {
-                if (b.buffer)
-                    free(b.buffer);
-                faacDecClose(hDecoder);
-                fclose(b.infile);
-                return 0;
-            }
             first_time = 0;
         }
 
         if ((frameInfo.error == 0) && (frameInfo.samples > 0))
         {
-            write_audio_file(aufile, sample_buffer, frameInfo.samples);
+            if(playback == 1)
+#ifdef _WIN32
+                WIN_Play_Samples((short*)sample_buffer, frameInfo.channels*frameInfo.samples);
+#else
+                fprintf(stderr, "Playback on anything other than WIN32 not possible.\n");
+#endif
+            else
+                write_audio_file(aufile, sample_buffer, frameInfo.samples);
         }
 
         /* fill buffer */
@@ -428,8 +458,15 @@
 
     fclose(b.infile);
 
-    if (!first_time)
-        close_audio_file(aufile);
+    if (playback == 1)
+    {
+#ifdef _WIN32
+        WIN_Audio_close();
+#endif
+    } else {
+        if (!first_time)
+            close_audio_file(aufile, sndfile);
+    }
 
     if (b.buffer)
         free(b.buffer);
@@ -479,7 +516,8 @@
 };
 
 int decodeMP4file(char *mp4file, char *sndfile, int to_stdout,
-                  int outputFormat, int fileType, int infoOnly)
+                  int outputFormat, int fileType, int infoOnly,
+                  int playback, unsigned int play_priority)
 {
     int track;
     unsigned int tracks;
@@ -526,7 +564,7 @@
         char *file_info;
         unsigned int i;
 
-        fprintf(stderr, "MP4 file info:\n");
+        fprintf(stderr, "%s file info:\n", mp4file);
         for (i = 0; i < tracks; i++)
         {
             file_info = MP4Info(infile, i+1);
@@ -607,29 +645,45 @@
         /* open the sound file now that the number of channels are known */
         if (first_time && !frameInfo.error)
         {
-            if(!to_stdout)
+            if (to_stdout)
+                sndfile = NULL;
+
+            if(playback == 1)
             {
-                aufile = open_audio_file(sndfile, frameInfo.samplerate, frameInfo.channels,
-                    outputFormat, fileType);
-            } else {
 #ifdef _WIN32
-                setmode(fileno(stdout), O_BINARY);
+                if (Set_WIN_Params (INVALID_FILEDESC, samplerate, SAMPLE_SIZE,
+                    frameInfo.channels, play_priority) < 0)
+                {
+                    fprintf(stderr, "\nCan't access %s\n", "WAVE OUT");
+                    faacDecClose(hDecoder);
+                    MP4Close(infile);
+                    return (0);
+                }
 #endif
-                aufile = open_audio_file("-", frameInfo.samplerate, frameInfo.channels,
+            } else {
+                aufile = open_audio_file(sndfile, frameInfo.samplerate, frameInfo.channels,
                     outputFormat, fileType);
+
+                if (aufile == NULL)
+                {
+                    faacDecClose(hDecoder);
+                    MP4Close(infile);
+                    return 0;
+                }
             }
-            if (aufile == NULL)
-            {
-                faacDecClose(hDecoder);
-                MP4Close(infile);
-                return 0;
-            }
             first_time = 0;
         }
 
         if ((frameInfo.error == 0) && (frameInfo.samples > 0))
         {
-            write_audio_file(aufile, sample_buffer, frameInfo.samples);
+            if (playback == 1)
+#ifdef _WIN32
+                WIN_Play_Samples((short*)sample_buffer, frameInfo.channels*frameInfo.samples);
+#else
+                fprintf(stderr, "Playback on anything other than WIN32 not possible.\n");
+#endif
+            else
+                write_audio_file(aufile, sample_buffer, frameInfo.samples);
         }
 
         if (frameInfo.error > 0)
@@ -644,8 +698,15 @@
 
     MP4Close(infile);
 
-    if (!first_time)
-        close_audio_file(aufile);
+    if (playback == 1)
+    {
+#ifdef _WIN32
+        WIN_Audio_close();
+#endif
+    } else {
+        if (!first_time)
+            close_audio_file(aufile, sndfile);
+    }
 
     return frameInfo.error;
 }
@@ -661,6 +722,8 @@
     int outputFormat = FAAD_FMT_16BIT;
     int outfile_set = 0;
     int showHelp = 0;
+    int playback = 0;
+    unsigned int play_priority = 1;
     int mp4file = 0;
     char *fnp;
     char aacFileName[255];
@@ -700,11 +763,13 @@
             { "samplerate", 0, 0, 's' },
             { "objecttype", 0, 0, 'l' },
             { "info",       0, 0, 'i' },
+            { "playback",   0, 0, 'p' },
+            { "priority",   0, 0, 'c' },
             { "stdio",      0, 0, 'w' },
             { "help",       0, 0, 'h' }
         };
 
-        c = getopt_long(argc, argv, "o:s:f:b:l:whi",
+        c = getopt_long(argc, argv, "o:s:f:b:l:whipc:",
             long_options, &option_index);
 
         if (c == -1)
@@ -768,7 +833,27 @@
                 }
             }
             break;
-        case 'w':
+#ifdef _WIN32
+        case 'p':
+            playback = 1;
+            break;
+        case 'c':
+            if (optarg) {
+                char dr[10];
+                if (sscanf(optarg, "%s", dr) < 1) {
+                    play_priority = 1; /* default */
+                } else {
+                    play_priority = atoi(dr);
+                    if(play_priority > 2)
+                    {
+                        fprintf(stderr, "Warning: priority class %s not recognised, using default\n", optarg);
+                        play_priority = 1;
+                    }
+                }
+            }
+            break;
+#endif
+        case 'w':
             writeToStdio = 1;
             break;
         case 'i':
@@ -823,10 +908,11 @@
     if (mp4file)
     {
         result = decodeMP4file(aacFileName, audioFileName, writeToStdio,
-            outputFormat, format, infoOnly);
+            outputFormat, format, infoOnly, playback, play_priority);
     } else {
         result = decodeAACfile(aacFileName, audioFileName, writeToStdio,
-            def_srate, object_type, outputFormat, format, infoOnly);
+            def_srate, object_type, outputFormat, format, infoOnly,
+            playback, play_priority);
     }
 
 
--- /dev/null
+++ b/frontend/wave_out.c
@@ -1,0 +1,212 @@
+/* Set TABS = 4 */
+/*
+** FAAD - Freeware Advanced Audio Decoder
+** Copyright (C) 2002 M. Bakker
+**
+** This program is free software; you can redistribute it and/or modify
+** it under the terms of the GNU General Public License as published by
+** the Free Software Foundation; either version 2 of the License, or
+** (at your option) any later version.
+**
+** This program is distributed in the hope that it will be useful,
+** but WITHOUT ANY WARRANTY; without even the implied warranty of
+** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+** GNU General Public License for more details.
+**
+** You should have received a copy of the GNU General Public License
+** along with this program; if not, write to the Free Software
+** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ ********************************************************************
+
+ function: To provide playback of 16 bit PCM wave data in Win32
+           environments from decoded aac/mp4 files.
+
+ ********************************************************************/
+
+#include <string.h>
+#include <errno.h>
+#include "wave_out.h"
+
+#ifdef _WIN32
+
+#define MAXWAVESIZE     4294967040LU
+#define MAX_WAVEBLOCKS    32
+
+static CRITICAL_SECTION  cs;
+static HWAVEOUT          dev                    = NULL;
+static int               ScheduledBlocks        = 0;
+static int               PlayedWaveHeadersCount = 0;          // free index
+static WAVEHDR*          PlayedWaveHeaders [MAX_WAVEBLOCKS];
+
+static int
+Box ( const char* msg )
+{
+	MessageBox ( NULL, msg, " Error Message . . .", MB_OK | MB_ICONEXCLAMATION );
+	return -1;
+}
+
+
+/*
+ *  This function registers already played WAVE chunks. Freeing is done by free_memory(),
+ */
+
+static void CALLBACK
+wave_callback ( HWAVE hWave, UINT uMsg, DWORD dwInstance, DWORD dwParam1, DWORD dwParam2 )
+{
+	if ( uMsg == WOM_DONE ) {
+		EnterCriticalSection ( &cs );
+		PlayedWaveHeaders [PlayedWaveHeadersCount++] = (WAVEHDR*) dwParam1;
+		LeaveCriticalSection ( &cs );
+	}
+}
+
+
+static void
+free_memory ( void )
+{
+	WAVEHDR*  wh;
+	HGLOBAL   hg;
+
+	EnterCriticalSection ( &cs );
+	wh = PlayedWaveHeaders [--PlayedWaveHeadersCount];
+	ScheduledBlocks--;                               // decrease the number of USED blocks
+	LeaveCriticalSection ( &cs );
+
+	waveOutUnprepareHeader ( dev, wh, sizeof (WAVEHDR) );
+
+	hg = GlobalHandle ( wh -> lpData );       // Deallocate the buffer memory
+	GlobalUnlock (hg);
+	GlobalFree   (hg);
+
+	hg = GlobalHandle ( wh );                 // Deallocate the header memory
+	GlobalUnlock (hg);
+	GlobalFree   (hg);
+}
+
+
+int
+Set_WIN_Params ( FILE_T           dummyFile ,
+                 long double      SampleFreq,
+                 unsigned int     BitsPerSample,
+                 unsigned int     Channels,
+                 unsigned int     play_priority )
+{
+	WAVEFORMATEX  outFormat;
+	UINT          deviceID = WAVE_MAPPER;
+
+	(void) dummyFile;
+
+	if ( waveOutGetNumDevs () == 0 )
+		return Box ( "No audio device present." );
+
+	outFormat.wFormatTag      = WAVE_FORMAT_PCM;
+	outFormat.wBitsPerSample  = BitsPerSample;
+	outFormat.nChannels       = Channels;
+	outFormat.nSamplesPerSec  = (unsigned long)(SampleFreq + 0.5);
+	outFormat.nBlockAlign     = (outFormat.wBitsPerSample + 7) / 8 * outFormat.nChannels;
+	outFormat.nAvgBytesPerSec = outFormat.nSamplesPerSec * outFormat.nBlockAlign;
+
+	switch ( waveOutOpen ( &dev, deviceID, &outFormat, (DWORD)wave_callback, 0, CALLBACK_FUNCTION ) )
+	{
+		case MMSYSERR_ALLOCATED:   return Box ( "Device is already open." );
+		case MMSYSERR_BADDEVICEID: return Box ( "The specified device is out of range." );
+		case MMSYSERR_NODRIVER:    return Box ( "There is no audio driver in this system." );
+		case MMSYSERR_NOMEM:       return Box ( "Unable to allocate sound memory." );
+		case WAVERR_BADFORMAT:     return Box ( "This audio format is not supported." );
+		case WAVERR_SYNC:          return Box ( "The device is synchronous." );
+		default:                   return Box ( "Unknown media error." );
+		case MMSYSERR_NOERROR:     break;
+	}
+
+	waveOutReset ( dev );
+	InitializeCriticalSection ( &cs );
+	switch(play_priority)
+	{
+		case 0:
+			SetPriorityClass ( GetCurrentProcess (), NORMAL_PRIORITY_CLASS );
+			break;
+		case 1:
+			SetPriorityClass ( GetCurrentProcess (), HIGH_PRIORITY_CLASS );
+			break;
+		case 2:
+			SetPriorityClass ( GetCurrentProcess (), REALTIME_PRIORITY_CLASS );
+			break;
+	}
+	return 0;
+}
+
+
+int
+WIN_Play_Samples ( const void* data, size_t len )
+{
+	HGLOBAL    hg;
+	HGLOBAL    hg2;
+	LPWAVEHDR  wh;
+	void*      allocptr;
+
+	do {
+		while ( PlayedWaveHeadersCount > 0 )                // free used blocks ...
+			free_memory ();
+
+		if ( ScheduledBlocks < sizeof(PlayedWaveHeaders)/sizeof(*PlayedWaveHeaders) ) // wait for a free block ...
+			break;
+		Sleep (26);
+	} while (1);
+
+	if ( (hg2 = GlobalAlloc ( GMEM_MOVEABLE, len )) == NULL )   // allocate some memory for a copy of the buffer
+		return Box ( "GlobalAlloc failed." );
+
+	allocptr = GlobalLock (hg2);
+	CopyMemory ( allocptr, data, len );                         // Here we can call any modification output functions we want....
+
+	if ( (hg = GlobalAlloc (GMEM_MOVEABLE | GMEM_ZEROINIT, sizeof (WAVEHDR))) == NULL ) // now make a header and WRITE IT!
+		return -1;
+
+	wh                   = GlobalLock (hg);
+	wh -> dwBufferLength = len;
+	wh -> lpData         = allocptr;
+
+	if ( waveOutPrepareHeader ( dev, wh, sizeof (WAVEHDR)) != MMSYSERR_NOERROR ) {
+		GlobalUnlock (hg);
+		GlobalFree   (hg);
+		return -1;
+	}
+
+	if ( waveOutWrite ( dev, wh, sizeof (WAVEHDR)) != MMSYSERR_NOERROR ) {
+		GlobalUnlock (hg);
+		GlobalFree   (hg);
+		return -1;
+	}
+
+	EnterCriticalSection ( &cs );
+	ScheduledBlocks++;
+	LeaveCriticalSection ( &cs );
+
+	return len;
+}
+
+
+int
+WIN_Audio_close ( void )
+{
+	if ( dev != NULL ) {
+
+		while ( ScheduledBlocks > 0 ) {
+			Sleep (ScheduledBlocks);
+			while ( PlayedWaveHeadersCount > 0 )         // free used blocks ...
+				free_memory ();
+		}
+
+		waveOutReset (dev);      // reset the device
+		waveOutClose (dev);      // close the device
+		dev = NULL;
+	}
+
+	DeleteCriticalSection ( &cs );
+	ScheduledBlocks = 0;
+	return 0;
+}
+
+#endif
+
+/* end of wave_out.c */
--- /dev/null
+++ b/frontend/wave_out.h
@@ -1,0 +1,45 @@
+/*
+** FAAD - Freeware Advanced Audio Decoder
+** Copyright (C) 2002 M. Bakker
+**
+** This program is free software; you can redistribute it and/or modify
+** it under the terms of the GNU General Public License as published by
+** the Free Software Foundation; either version 2 of the License, or
+** (at your option) any later version.
+**
+** This program is distributed in the hope that it will be useful,
+** but WITHOUT ANY WARRANTY; without even the implied warranty of
+** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+** GNU General Public License for more details.
+**
+** You should have received a copy of the GNU General Public License
+** along with this program; if not, write to the Free Software
+** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+//    WAVE_OUT.H - Necessary stuff for WIN_AUDIO
+
+#include <stdio.h>
+#include <windows.h>
+
+#define Cdecl               __cdecl
+#define __attribute__(x)
+#define sleep(__sec)        Sleep ((__sec) * 1000)
+#define inline              __inline
+#define restrict
+
+//// constants /////////////////////////////////////////////////////
+
+#define CD_SAMPLE_FREQ         44.1e3
+#define SAMPLE_SIZE            16
+#define SAMPLE_SIZE_STRING     ""
+#define WINAUDIO_FD            ((FILE_T)-128)
+#define FILE_T                 FILE*
+#define INVALID_FILEDESC       NULL
+
+//// procedures/functions //////////////////////////////////////////
+// wave_out.c
+int        Set_WIN_Params             ( FILE_T dummyFile , long double SampleFreq, unsigned int BitsPerSample, unsigned int Channels, unsigned int play_priority );
+int        WIN_Play_Samples           ( const void* buff, size_t len );
+int        WIN_Audio_close            ( void );
+
--- a/include/faad.h
+++ b/include/faad.h
@@ -16,7 +16,7 @@
 ** along with this program; if not, write to the Free Software
 ** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 **
-** $Id: faad.h,v 1.21 2003/04/02 20:07:45 menno Exp $
+** $Id: faad.h,v 1.22 2003/07/07 21:11:18 menno Exp $
 **/
 
 #ifndef __AACDEC_H__
@@ -47,7 +47,7 @@
 #define ER_LC     17
 #define ER_LTP    19
 #define LD        23
-#define DRM_ER_LC 27 /* special object type for DRM */
+#define DRM_ER_LC 32 /* special object type for DRM */
 
 /* header types */
 #define RAW        0
@@ -73,8 +73,21 @@
 #define ERROR_RESILIENCE_CAP  (1<<4)
 #define FIXED_POINT_CAP       (1<<5)
 
-/* A decode call can eat up to FAAD_MIN_STREAMSIZE octets per decoded channel,
-   so at least so much octets per channel should be available in this stream */
+/* Channel definitions */
+#define FRONT_CHANNEL_CENTER (1)
+#define FRONT_CHANNEL_LEFT   (2)
+#define FRONT_CHANNEL_RIGHT  (3)
+#define SIDE_CHANNEL_LEFT    (4)
+#define SIDE_CHANNEL_RIGHT   (5)
+#define BACK_CHANNEL_LEFT    (6)
+#define BACK_CHANNEL_RIGHT   (7)
+#define BACK_CHANNEL_CENTER  (8)
+#define LFE_CHANNEL          (9)
+#define UNKNOWN_CHANNEL      (10)
+
+
+/* A decode call can eat up to FAAD_MIN_STREAMSIZE bytes per decoded channel,
+   so at least so much bytes per channel should be available in this stream */
 #define FAAD_MIN_STREAMSIZE 768 /* 6144 bits/channel */
 
 
@@ -114,6 +127,9 @@
     unsigned char channels;
     unsigned char error;
     unsigned long samplerate;
+
+    /* multichannel configuration */
+    unsigned char channel_config[64];
 } faacDecFrameInfo;
 
 char* FAADAPI faacDecGetErrorMessage(unsigned char errcode);
--- a/libfaad/Makefile.am
+++ b/libfaad/Makefile.am
@@ -8,7 +8,7 @@
 rvlc.c ssr.c ssr_fb.c ssr_ipqf.c common.c
 
 libfaad_la_INCLUDES = analysis.h bits.h cfft.h cfft_tab.h common.h \
-data.h decoder.h dither.h drc.h error.h fixed.h filtbank.h \
+decoder.h dither.h drc.h error.h fixed.h filtbank.h \
 huffman.h ic_predict.h iq_table.h is.h kbd_win.h lt_predict.h mdct.h mp4.h \
 ms.h output.h pns.h pulse.h rvlc.h sine_win.h ssr.h ssr_fb.h ssr_ipqf.h \
 ssr_win.h specrec.h syntax.h tns.h codebook/hcb.h \
--- a/libfaad/bits.h
+++ b/libfaad/bits.h
@@ -16,7 +16,7 @@
 ** along with this program; if not, write to the Free Software 
 ** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 **
-** $Id: bits.h,v 1.17 2003/04/01 16:34:30 menno Exp $
+** $Id: bits.h,v 1.18 2003/07/07 21:11:18 menno Exp $
 **/
 
 #ifndef __BITS_H__
@@ -162,7 +162,7 @@
         return (uint8_t)faad_getbits(ld, 1 DEBUGVAR(print,var,dbg));
 
     ld->bits_left--;
-    r = (ld->bufa >> ld->bits_left) & 1;
+    r = (uint8_t)((ld->bufa >> ld->bits_left) & 1);
 
     return r;
 }
--- a/libfaad/decoder.c
+++ b/libfaad/decoder.c
@@ -16,7 +16,7 @@
 ** along with this program; if not, write to the Free Software 
 ** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 **
-** $Id: decoder.c,v 1.57 2003/06/23 15:21:19 menno Exp $
+** $Id: decoder.c,v 1.58 2003/07/07 21:11:18 menno Exp $
 **/
 
 #include "common.h"
@@ -178,12 +178,15 @@
             get_adif_header(&adif, &ld);
             faad_byte_align(&ld);
 
-            hDecoder->sf_index = adif.pce.sf_index;
-            hDecoder->object_type = adif.pce.object_type;
+            hDecoder->sf_index = adif.pce[0].sf_index;
+            hDecoder->object_type = adif.pce[0].object_type;
 
             *samplerate = sample_rates[hDecoder->sf_index];
-            *channels = adif.pce.channels;
+            *channels = adif.pce[0].channels;
 
+            memcpy(&(hDecoder->pce), &(adif.pce[0]), sizeof(program_config));
+            hDecoder->pce_set = 1;
+
             bits = bit2byte(faad_get_processed_bits(&ld));
 
         /* Check if an ADTS header is present */
@@ -403,8 +406,8 @@
 #ifdef LTP_DEC
     uint16_t *ltp_lag      =  hDecoder->ltp_lag;
 #endif
+    program_config *pce    = &(hDecoder->pce);
 
-    program_config pce;
     element *syntax_elements[MAX_SYNTAX_ELEMENTS];
     element **elements;
     int16_t *spec_data[MAX_CHANNELS];
@@ -447,7 +450,7 @@
 
     /* decode the complete bitstream */
     elements = raw_data_block(hDecoder, hInfo, ld, syntax_elements,
-        spec_data, spec_coef, &pce, drc);
+        spec_data, spec_coef, pce, drc);
 
     ch_ele = hDecoder->fr_ch_ele;
     channels = hDecoder->fr_channels;
@@ -497,13 +500,10 @@
         ic_stream *ics;
 
         /* find the syntax element to which this channel belongs */
-        for (i = 0; i < ch_ele; i++)
-        {
-            if (syntax_elements[i]->channel == ch)
-                ics = &(syntax_elements[i]->ics1);
-            else if (syntax_elements[i]->paired_channel == ch)
-                ics = &(syntax_elements[i]->ics2);
-        }
+        if (syntax_elements[hDecoder->channel_element[ch]]->channel == ch)
+            ics = &(syntax_elements[hDecoder->channel_element[ch]]->ics1);
+        else if (syntax_elements[hDecoder->channel_element[ch]]->paired_channel == ch)
+            ics = &(syntax_elements[hDecoder->channel_element[ch]]->ics2);
 
         /* inverse quantization */
         inverse_quantization(spec_coef[ch], spec_data[ch], frame_len);
@@ -518,18 +518,6 @@
         /* deinterleave short block grouping */
         if (ics->window_sequence == EIGHT_SHORT_SEQUENCE)
             quant_to_spec(ics, spec_coef[ch], frame_len);
-
-#if 0
-        {
-            int rr;
-
-            for (rr = 0; rr < frame_len; rr++)
-            {
-//                if ((spec_coef[ch][rr] >> REAL_BITS) > (1<<12))
-                    printf(">>> %d\n", (spec_coef[ch][rr] >> REAL_BITS));
-            }
-        }
-#endif
     }
 
     /* Because for ms, is and pns both channels spectral coefficients are needed
@@ -543,23 +531,20 @@
         ltp_info *ltp;
 
         /* find the syntax element to which this channel belongs */
-        for (i = 0; i < ch_ele; i++)
+        if (syntax_elements[hDecoder->channel_element[ch]]->channel == ch)
         {
-            if (syntax_elements[i]->channel == ch)
-            {
-                ics = &(syntax_elements[i]->ics1);
-                icsr = &(syntax_elements[i]->ics2);
-                ltp = &(ics->ltp);
-                pch = syntax_elements[i]->paired_channel;
-                right_channel = 0;
-            } else if (syntax_elements[i]->paired_channel == ch) {
-                ics = &(syntax_elements[i]->ics2);
-                if (syntax_elements[i]->common_window)
-                    ltp = &(ics->ltp2);
-                else
-                    ltp = &(ics->ltp);
-                right_channel = 1;
-            }
+            ics = &(syntax_elements[hDecoder->channel_element[ch]]->ics1);
+            icsr = &(syntax_elements[hDecoder->channel_element[ch]]->ics2);
+            ltp = &(ics->ltp);
+            pch = syntax_elements[hDecoder->channel_element[ch]]->paired_channel;
+            right_channel = 0;
+        } else if (syntax_elements[hDecoder->channel_element[ch]]->paired_channel == ch) {
+            ics = &(syntax_elements[hDecoder->channel_element[ch]]->ics2);
+            if (syntax_elements[hDecoder->channel_element[ch]]->common_window)
+                ltp = &(ics->ltp2);
+            else
+                ltp = &(ics->ltp);
+            right_channel = 1;
         }
 
         /* pns decoding */
--- a/libfaad/decoder.h
+++ b/libfaad/decoder.h
@@ -16,7 +16,7 @@
 ** along with this program; if not, write to the Free Software 
 ** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 **
-** $Id: decoder.h,v 1.22 2003/04/02 20:07:46 menno Exp $
+** $Id: decoder.h,v 1.23 2003/07/07 21:11:18 menno Exp $
 **/
 
 #ifndef __DECODER_H__
@@ -64,6 +64,18 @@
 #define LD_DEC_CAP            (1<<3)
 #define ERROR_RESILIENCE_CAP  (1<<4)
 #define FIXED_POINT_CAP       (1<<5)
+
+/* channel definitions */
+#define FRONT_CHANNEL_CENTER (1)
+#define FRONT_CHANNEL_LEFT   (2)
+#define FRONT_CHANNEL_RIGHT  (3)
+#define SIDE_CHANNEL_LEFT    (4)
+#define SIDE_CHANNEL_RIGHT   (5)
+#define BACK_CHANNEL_LEFT    (6)
+#define BACK_CHANNEL_RIGHT   (7)
+#define BACK_CHANNEL_CENTER  (8)
+#define LFE_CHANNEL          (9)
+#define UNKNOWN_CHANNEL      (10)
 
 int8_t* FAADAPI faacDecGetErrorMessage(uint8_t errcode);
 
--- a/libfaad/output.c
+++ b/libfaad/output.c
@@ -16,7 +16,7 @@
 ** along with this program; if not, write to the Free Software 
 ** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 **
-** $Id: output.c,v 1.16 2003/04/26 13:25:13 menno Exp $
+** $Id: output.c,v 1.17 2003/07/07 21:11:18 menno Exp $
 **/
 
 #include "common.h"
@@ -56,11 +56,11 @@
     double    *double_sample_buffer = (double*)sample_buffer;
 
     /* Copy output to a standard PCM buffer */
-    switch (format)
+    for (ch = 0; ch < channels; ch++)
     {
-    case FAAD_FMT_16BIT:
-        for (ch = 0; ch < channels; ch++)
+        switch (format)
         {
+        case FAAD_FMT_16BIT:
             for(i = 0; i < frame_len; i++)
             {
                 int32_t tmp;
@@ -69,11 +69,8 @@
                 ftemp = input[ch][i] + 0xff8000;
                 ftol(ftemp, short_sample_buffer[(i*channels)+ch]);
             }
-        }
-        break;
-    case FAAD_FMT_16BIT_DITHER:
-        for (ch = 0; ch < channels; ch++)
-        {
+            break;
+        case FAAD_FMT_16BIT_DITHER:
             for(i = 0; i < frame_len; i++, j++)
             {
                 double Sum = input[ch][i] * 65535.f;
@@ -87,13 +84,10 @@
                     val = -(1<<15);
                 short_sample_buffer[(i*channels)+ch] = (int16_t)val;
             }
-        }
-        break;
-    case FAAD_FMT_16BIT_L_SHAPE:
-    case FAAD_FMT_16BIT_M_SHAPE:
-    case FAAD_FMT_16BIT_H_SHAPE:
-        for (ch = 0; ch < channels; ch++)
-        {
+            break;
+        case FAAD_FMT_16BIT_L_SHAPE:
+        case FAAD_FMT_16BIT_M_SHAPE:
+        case FAAD_FMT_16BIT_H_SHAPE:
             for(i = 0; i < frame_len; i++, j++)
             {
                 double Sum = input[ch][i] * 65535.f;
@@ -107,11 +101,8 @@
                     val = -(1<<15);
                 short_sample_buffer[(i*channels)+ch] = (int16_t)val;
             }
-        }
-        break;
-    case FAAD_FMT_24BIT:
-        for (ch = 0; ch < channels; ch++)
-        {
+            break;
+        case FAAD_FMT_24BIT:
             for(i = 0; i < frame_len; i++)
             {
                 if (input[ch][i] > (1<<15)-1)
@@ -120,11 +111,8 @@
                     input[ch][i] = -(1<<15);
                 int_sample_buffer[(i*channels)+ch] = ROUND(input[ch][i]*(1<<8));
             }
-        }
-        break;
-    case FAAD_FMT_32BIT:
-        for (ch = 0; ch < channels; ch++)
-        {
+            break;
+        case FAAD_FMT_32BIT:
             for(i = 0; i < frame_len; i++)
             {
                 if (input[ch][i] > (1<<15)-1)
@@ -133,38 +121,20 @@
                     input[ch][i] = -(1<<15);
                 int_sample_buffer[(i*channels)+ch] = ROUND32(input[ch][i]*(1<<16));
             }
-        }
-        break;
-    case FAAD_FMT_FLOAT:
-        for (ch = 0; ch < channels; ch++)
-        {
+            break;
+        case FAAD_FMT_FLOAT:
             for(i = 0; i < frame_len; i++)
             {
-/*
-                if (input[ch][i] > (1<<15)-1)
-                    input[ch][i] = (1<<15)-1;
-                else if (input[ch][i] < -(1<<15))
-                    input[ch][i] = -(1<<15);
-*/
                 float_sample_buffer[(i*channels)+ch] = input[ch][i]*FLOAT_SCALE;
             }
-        }
-        break;
-    case FAAD_FMT_DOUBLE:
-        for (ch = 0; ch < channels; ch++)
-        {
+            break;
+        case FAAD_FMT_DOUBLE:
             for(i = 0; i < frame_len; i++)
             {
-/*
-                if (input[ch][i] > (1<<15)-1)
-                    input[ch][i] = (1<<15)-1;
-                else if (input[ch][i] < -(1<<15))
-                    input[ch][i] = -(1<<15);
-*/
                 double_sample_buffer[(i*channels)+ch] = (double)input[ch][i]*FLOAT_SCALE;
             }
+            break;
         }
-        break;
     }
 
     return sample_buffer;
--- a/libfaad/structs.h
+++ b/libfaad/structs.h
@@ -16,7 +16,7 @@
 ** along with this program; if not, write to the Free Software 
 ** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 **
-** $Id: structs.h,v 1.5 2003/02/09 20:42:49 menno Exp $
+** $Id: structs.h,v 1.6 2003/07/07 21:11:18 menno Exp $
 **/
 
 #ifndef __STRUCTS_H__
@@ -155,7 +155,8 @@
     uint8_t num_program_config_elements;
     uint32_t adif_buffer_fullness;
 
-    program_config pce;
+    /* maximum of 16 PCEs */
+    program_config pce[16];
 } adif_header;
 
 typedef struct
@@ -314,6 +315,9 @@
     uint8_t channels;
     uint8_t error;
     uint32_t samplerate;
+
+    /* multichannel configuration */
+    uint8_t channel_config[64];
 } faacDecFrameInfo;
 
 typedef struct
@@ -364,6 +368,11 @@
     real_t *pow2_table;
 #endif
 #endif
+
+    /* Program Config Element */
+    uint8_t pce_set;
+    program_config pce;
+    uint8_t channel_element[MAX_CHANNELS];
 
     /* Configuration data */
     faacDecConfiguration config;
--- a/libfaad/syntax.c
+++ b/libfaad/syntax.c
@@ -16,7 +16,7 @@
 ** along with this program; if not, write to the Free Software 
 ** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 **
-** $Id: syntax.c,v 1.45 2003/06/23 15:21:20 menno Exp $
+** $Id: syntax.c,v 1.46 2003/07/07 21:11:18 menno Exp $
 **/
 
 /*
@@ -65,8 +65,10 @@
         program_config_element(&pce, ld);
         mp4ASC->channelsConfiguration = pce.channels;
 
+        /*
         if (pce.num_valid_cc_elements)
             return -3;
+        */
     }
 
 #ifdef ERROR_RESILIENCE
@@ -154,12 +156,16 @@
         if ((pce->front_element_is_cpe[i] = faad_get1bit(ld
             DEBUGVAR(1,26,"program_config_element(): front_element_is_cpe"))) & 1)
         {
+//            printf("CPE ");
             pce->channels += 2;
         } else {
+//            printf("SCE ");
             pce->channels++;
         }
         pce->front_element_tag_select[i] = (uint8_t)faad_getbits(ld, 4
             DEBUGVAR(1,27,"program_config_element(): front_element_tag_select"));
+
+//        printf("FRONT %d: %d\n", i, pce->front_element_tag_select[i]);
     }
 
     for (i = 0; i < pce->num_side_channel_elements; i++)
@@ -167,12 +173,16 @@
         if ((pce->side_element_is_cpe[i] = faad_get1bit(ld
             DEBUGVAR(1,28,"program_config_element(): side_element_is_cpe"))) & 1)
         {
+//            printf("CPE ");
             pce->channels += 2;
         } else {
+//            printf("SCE ");
             pce->channels++;
         }
         pce->side_element_tag_select[i] = (uint8_t)faad_getbits(ld, 4
             DEBUGVAR(1,29,"program_config_element(): side_element_tag_select"));
+
+//        printf("SIDE %d: %d\n", i, pce->side_element_tag_select[i]);
     }
 
     for (i = 0; i < pce->num_back_channel_elements; i++)
@@ -180,12 +190,16 @@
         if ((pce->back_element_is_cpe[i] = faad_get1bit(ld
             DEBUGVAR(1,30,"program_config_element(): back_element_is_cpe"))) & 1)
         {
+//            printf("CPE ");
             pce->channels += 2;
         } else {
+//            printf("SCE ");
             pce->channels++;
         }
         pce->back_element_tag_select[i] = (uint8_t)faad_getbits(ld, 4
             DEBUGVAR(1,31,"program_config_element(): back_element_tag_select"));
+
+//        printf("BACK %d: %d\n", i, pce->back_element_tag_select[i]);
     }
 
     for (i = 0; i < pce->num_lfe_channel_elements; i++)
@@ -193,17 +207,18 @@
         pce->channels++;
         pce->lfe_element_tag_select[i] = (uint8_t)faad_getbits(ld, 4
             DEBUGVAR(1,32,"program_config_element(): lfe_element_tag_select"));
+
+//        printf("LFE %d: %d\n", i, pce->lfe_element_tag_select[i]);
     }
 
     for (i = 0; i < pce->num_assoc_data_elements; i++)
+    {
         pce->assoc_data_element_tag_select[i] = (uint8_t)faad_getbits(ld, 4
-        DEBUGVAR(1,33,"program_config_element(): assoc_data_element_tag_select"));
+            DEBUGVAR(1,33,"program_config_element(): assoc_data_element_tag_select"));
+    }
 
     for (i = 0; i < pce->num_valid_cc_elements; i++)
     {
-        /* have to count these as channels too?? (1 or 2) */
-        pce->channels += 2;
-
         pce->cc_element_is_ind_sw[i] = faad_get1bit(ld
             DEBUGVAR(1,34,"program_config_element(): cc_element_is_ind_sw"));
         pce->valid_cc_element_tag_select[i] = (uint8_t)faad_getbits(ld, 4
@@ -256,6 +271,11 @@
     hInfo->error = single_lfe_channel_element(hDecoder, ele,
         ld, spec_data[channels]);
 
+    if (id_syn_ele == ID_SCE)
+        hDecoder->channel_element[channels] = hDecoder->fr_ch_ele;
+    else /* LFE */
+        hDecoder->channel_element[channels] = hDecoder->fr_ch_ele;
+
     hDecoder->fr_channels++;
     hDecoder->fr_ch_ele++;
 
@@ -295,6 +315,9 @@
     hInfo->error = channel_pair_element(hDecoder, ele,
         ld, spec_data[channels], spec_data[channels+1]);
 
+    hDecoder->channel_element[channels] = hDecoder->fr_ch_ele;
+    hDecoder->channel_element[channels+1] = hDecoder->fr_ch_ele;
+
     hDecoder->fr_channels += 2;
     hDecoder->fr_ch_ele++;
 
@@ -334,9 +357,11 @@
                 if (hInfo->error > 0)
                     return elements;
                 break;
-            case ID_CCE: /* not implemented yet */
-                hInfo->error = 6;
-                return elements;
+            case ID_CCE: /* not implemented yet, but skip the bits */
+                hInfo->error = coupling_channel_element(hDecoder, ld);
+                if (hInfo->error > 0)
+                    return elements;
+                break;
             case ID_DSE:
                 data_stream_element(ld);
                 break;
@@ -343,6 +368,7 @@
             case ID_PCE:
                 if ((hInfo->error = program_config_element(pce, ld)) > 0)
                     return elements;
+                hDecoder->pce_set = 1;
                 break;
             case ID_FIL:
                 if ((hInfo->error = fill_element(ld, drc)) > 0)
@@ -775,6 +801,97 @@
     return 0;
 }
 
+/* Table 4.4.8: Currently just for skipping the bits... */
+static uint8_t coupling_channel_element(faacDecHandle hDecoder, bitfile *ld)
+{
+    uint8_t c, result = 0;
+    uint8_t ind_sw_cce_flag = 0;
+    uint8_t num_gain_element_lists = 0;
+    uint8_t num_coupled_elements = 0;
+
+    element el_empty;
+    ic_stream ics_empty;
+    int16_t sh_data[1024];
+
+    memset(&el_empty, 0, sizeof(element));
+    memset(&ics_empty, 0, sizeof(ic_stream));
+
+    faad_getbits(ld, LEN_TAG
+        DEBUGVAR(1,900,"coupling_channel_element(): element_instance_tag"));
+
+    ind_sw_cce_flag = faad_get1bit(ld
+        DEBUGVAR(1,901,"coupling_channel_element(): ind_sw_cce_flag"));
+    num_coupled_elements = faad_getbits(ld, 3
+        DEBUGVAR(1,902,"coupling_channel_element(): num_coupled_elements"));
+
+    for (c = 0; c < num_coupled_elements + 1; c++)
+    {
+        uint8_t cc_target_is_cpe, cc_target_tag_select;
+
+        num_gain_element_lists++;
+
+        cc_target_is_cpe = faad_get1bit(ld
+            DEBUGVAR(1,903,"coupling_channel_element(): cc_target_is_cpe"));
+        cc_target_tag_select = faad_getbits(ld, 4
+            DEBUGVAR(1,904,"coupling_channel_element(): cc_target_tag_select"));
+
+        if (cc_target_is_cpe)
+        {
+            uint8_t cc_l = faad_get1bit(ld
+                DEBUGVAR(1,905,"coupling_channel_element(): cc_l"));
+            uint8_t cc_r = faad_get1bit(ld
+                DEBUGVAR(1,906,"coupling_channel_element(): cc_r"));
+
+            if (cc_l && cc_r)
+                num_gain_element_lists++;
+        }
+    }
+
+    faad_get1bit(ld
+        DEBUGVAR(1,907,"coupling_channel_element(): cc_domain"));
+    faad_get1bit(ld
+        DEBUGVAR(1,908,"coupling_channel_element(): gain_element_sign"));
+    faad_getbits(ld, 2
+        DEBUGVAR(1,909,"coupling_channel_element(): gain_element_scale"));
+
+    if ((result = individual_channel_stream(hDecoder, &el_empty, ld, &ics_empty,
+        0, sh_data)) > 0)
+    {
+        return result;
+    }
+
+    for (c = 1; c < num_gain_element_lists; c++)
+    {
+        uint8_t cge;
+
+        if (ind_sw_cce_flag)
+        {
+            cge = 1;
+        } else {
+            cge = faad_get1bit(ld
+                DEBUGVAR(1,910,"coupling_channel_element(): common_gain_element_present"));
+        }
+
+        if (cge)
+        {
+            huffman_scale_factor(ld);
+        } else {
+            uint8_t g, sfb;
+
+            for (g = 0; g < ics_empty.num_window_groups; g++)
+            {
+                for (sfb = 0; sfb < ics_empty.max_sfb; sfb++)
+                {
+                    if (ics_empty.sfb_cb[g][sfb] != ZERO_HCB)
+                        huffman_scale_factor(ld);
+                }
+            }
+        }
+    }
+
+    return 0;
+}
+
 /* Table 4.4.10 */
 static uint16_t data_stream_element(bitfile *ld)
 {
@@ -1624,17 +1741,17 @@
     adif->num_program_config_elements = (uint8_t)faad_getbits(ld, 4
         DEBUGVAR(1,116,"get_adif_header(): num_program_config_elements"));
 
-    if(adif->bitstream_type == 0)
-    {
-        adif->adif_buffer_fullness = faad_getbits(ld, 20
-            DEBUGVAR(1,117,"get_adif_header(): adif_buffer_fullness"));
-    } else {
-        adif->adif_buffer_fullness = 0;
-    }
-
     for (i = 0; i < adif->num_program_config_elements + 1; i++)
     {
-        program_config_element(&adif->pce, ld);
+        if(adif->bitstream_type == 0)
+        {
+            adif->adif_buffer_fullness = faad_getbits(ld, 20
+                DEBUGVAR(1,117,"get_adif_header(): adif_buffer_fullness"));
+        } else {
+            adif->adif_buffer_fullness = 0;
+        }
+
+        program_config_element(&adif->pce[i], ld);
     }
 }
 
--- a/libfaad/syntax.h
+++ b/libfaad/syntax.h
@@ -16,7 +16,7 @@
 ** along with this program; if not, write to the Free Software 
 ** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 **
-** $Id: syntax.h,v 1.28 2003/06/23 15:21:20 menno Exp $
+** $Id: syntax.h,v 1.30 2003/07/08 13:45:45 menno Exp $
 **/
 
 #ifndef __SYNTAX_H__
@@ -99,6 +99,7 @@
 static uint8_t channel_pair_element(faacDecHandle hDecoder, element *cpe,
                                     bitfile *ld, int16_t *spec_data1,
                                     int16_t *spec_data2);
+static uint8_t coupling_channel_element(faacDecHandle hDecoder, bitfile *ld);
 static uint16_t data_stream_element(bitfile *ld);
 static uint8_t program_config_element(program_config *pce, bitfile *ld);
 static uint8_t fill_element(bitfile *ld, drc_info *drc);