shithub: aacdec

Download patch

ref: c12d8b8c3a448a01865b6b3f15b0452ea67b9a8f
parent: e98a69b9db88ef00994bbc7a95add426a36adcf6
author: menno <menno>
date: Tue Jul 8 09:45:45 EDT 2003

reverted some changes in the frontend
better multichannel support

--- 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.13 2003/07/07 21:11:17 menno Exp $
+** $Id: audio.c,v 1.14 2003/07/08 13:45:45 menno Exp $
 **/
 
 #ifdef _WIN32
@@ -63,17 +63,13 @@
         return NULL;
     }
 
-    if(!infile)
+#ifdef _WIN32
+    if(infile[0] == '-')
     {
-#ifdef __BORLANDC__
         setmode(fileno(stdout), O_BINARY);
-#elif defined _MSC_VER || defined __MINGW32__
-        _setmode(_fileno(stdout), _O_BINARY);
-#endif
-        aufile->sndfile = stdout;
-    } else {
-        aufile->sndfile = fopen(infile, "wb");
     }
+#endif
+    aufile->sndfile = fopen(infile, "wb");
 
     if (aufile->sndfile == NULL)
     {
@@ -84,7 +80,6 @@
     if (aufile->fileType == OUTPUT_WAV)
     {
         write_wav_header(aufile);
-        aufile->total_samples = 0;
     }
 
     return aufile;
@@ -113,16 +108,17 @@
     return 0;
 }
 
-void close_audio_file(audio_file *aufile, char *fileName)
+void close_audio_file(audio_file *aufile)
 {
-    if (aufile->fileType == OUTPUT_WAV && fileName)
+    if (aufile->fileType == OUTPUT_WAV)
     {
         fseek(aufile->sndfile, 0, SEEK_SET);
 
         write_wav_header(aufile);
-        fclose(aufile->sndfile);
     }
 
+    fclose(aufile->sndfile);
+
     if (aufile) free(aufile);
 }
 
@@ -131,13 +127,8 @@
     unsigned char header[44];
     unsigned char* p = header;
     unsigned int bytes = (aufile->bits_per_sample + 7) / 8;
-    float data_size;
+    float data_size = (float)bytes * aufile->total_samples;
     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.6 2003/07/07 21:11:17 menno Exp $
+** $Id: audio.h,v 1.7 2003/07/08 13:45:45 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, char *fileName);
+void close_audio_file(audio_file *aufile);
 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
@@ -97,10 +97,6 @@
 
 SOURCE=.\main.c
 # End Source File
-# Begin Source File
-
-SOURCE=.\wave_out.c
-# End Source File
 # End Group
 # Begin Group "Header Files"
 
@@ -128,10 +124,6 @@
 # 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.37 2003/07/07 21:11:17 menno Exp $
+** $Id: main.c,v 1.38 2003/07/08 13:45:45 menno Exp $
 **/
 
 #ifdef _WIN32
@@ -34,17 +34,14 @@
 #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 8 /* make this higher to support files with
-                          more channels */
+#define MAX_CHANNELS 6 /* make this higher to support files with
 
+                          more channels */
 /* FAAD file buffering routines */
 typedef struct {
     long bytes_into_buffer;
@@ -201,14 +198,6 @@
     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");
@@ -219,7 +208,7 @@
 
 int decodeAACfile(char *aacfile, char *sndfile, int to_stdout,
                   int def_srate, int object_type, int outputFormat, int fileType,
-                  int infoOnly, int playback, unsigned int play_priority)
+                  int infoOnly)
 {
     int tagsize;
     unsigned long samplerate;
@@ -400,49 +389,28 @@
         /* open the sound file now that the number of channels are known */
         if (first_time && !frameInfo.error)
         {
-            if(to_stdout)
-                sndfile = NULL;
-
-            if(playback == 1)
+            if (!to_stdout)
             {
-#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);
-
-                if (aufile == NULL)
-                {
-                    if (b.buffer)
-                        free(b.buffer);
-                    faacDecClose(hDecoder);
-                    fclose(b.infile);
-                    return 0;
-                }
+            } 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;
+            }
             first_time = 0;
         }
 
         if ((frameInfo.error == 0) && (frameInfo.samples > 0))
         {
-            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);
+            write_audio_file(aufile, sample_buffer, frameInfo.samples);
         }
 
         /* fill buffer */
@@ -458,15 +426,8 @@
 
     fclose(b.infile);
 
-    if (playback == 1)
-    {
-#ifdef _WIN32
-        WIN_Audio_close();
-#endif
-    } else {
-        if (!first_time)
-            close_audio_file(aufile, sndfile);
-    }
+    if (!first_time)
+        close_audio_file(aufile);
 
     if (b.buffer)
         free(b.buffer);
@@ -516,8 +477,7 @@
 };
 
 int decodeMP4file(char *mp4file, char *sndfile, int to_stdout,
-                  int outputFormat, int fileType, int infoOnly,
-                  int playback, unsigned int play_priority)
+                  int outputFormat, int fileType, int infoOnly)
 {
     int track;
     unsigned int tracks;
@@ -645,45 +605,29 @@
         /* open the sound file now that the number of channels are known */
         if (first_time && !frameInfo.error)
         {
-            if (to_stdout)
-                sndfile = NULL;
-
-            if(playback == 1)
+            if(!to_stdout)
             {
+                aufile = open_audio_file(sndfile, frameInfo.samplerate, frameInfo.channels,
+                    outputFormat, fileType);
+            } else {
 #ifdef _WIN32
-                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);
-                }
+                setmode(fileno(stdout), O_BINARY);
 #endif
-            } else {
-                aufile = open_audio_file(sndfile, frameInfo.samplerate, frameInfo.channels,
+                aufile = open_audio_file("-", 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))
         {
-            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);
+            write_audio_file(aufile, sample_buffer, frameInfo.samples);
         }
 
         if (frameInfo.error > 0)
@@ -698,15 +642,8 @@
 
     MP4Close(infile);
 
-    if (playback == 1)
-    {
-#ifdef _WIN32
-        WIN_Audio_close();
-#endif
-    } else {
-        if (!first_time)
-            close_audio_file(aufile, sndfile);
-    }
+    if (!first_time)
+        close_audio_file(aufile);
 
     return frameInfo.error;
 }
@@ -722,8 +659,6 @@
     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];
@@ -763,13 +698,11 @@
             { "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:whipc:",
+        c = getopt_long(argc, argv, "o:s:f:b:l:whi",
             long_options, &option_index);
 
         if (c == -1)
@@ -833,27 +766,7 @@
                 }
             }
             break;
-#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':
+        case 'w':
             writeToStdio = 1;
             break;
         case 'i':
@@ -908,11 +821,10 @@
     if (mp4file)
     {
         result = decodeMP4file(aacFileName, audioFileName, writeToStdio,
-            outputFormat, format, infoOnly, playback, play_priority);
+            outputFormat, format, infoOnly);
     } else {
         result = decodeAACfile(aacFileName, audioFileName, writeToStdio,
-            def_srate, object_type, outputFormat, format, infoOnly,
-            playback, play_priority);
+            def_srate, object_type, outputFormat, format, infoOnly);
     }
 
 
--- a/frontend/wave_out.c
+++ /dev/null
@@ -1,212 +1,0 @@
-/* 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 */
--- a/frontend/wave_out.h
+++ /dev/null
@@ -1,45 +1,0 @@
-/*
-** 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.22 2003/07/07 21:11:18 menno Exp $
+** $Id: faad.h,v 1.23 2003/07/08 13:45:45 menno Exp $
 **/
 
 #ifndef __AACDEC_H__
@@ -47,7 +47,7 @@
 #define ER_LC     17
 #define ER_LTP    19
 #define LD        23
-#define DRM_ER_LC 32 /* special object type for DRM */
+#define DRM_ER_LC 27 /* special object type for DRM */
 
 /* header types */
 #define RAW        0
@@ -129,7 +129,11 @@
     unsigned long samplerate;
 
     /* multichannel configuration */
-    unsigned char channel_config[64];
+    unsigned char num_front_channels;
+    unsigned char num_side_channels;
+    unsigned char num_back_channels;
+    unsigned char num_lfe_channels;
+    unsigned char channel_position[64];
 } faacDecFrameInfo;
 
 char* FAADAPI faacDecGetErrorMessage(unsigned char errcode);
--- 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.18 2003/07/07 21:11:18 menno Exp $
+** $Id: bits.h,v 1.19 2003/07/08 13:45:45 menno Exp $
 **/
 
 #ifndef __BITS_H__
@@ -162,7 +162,7 @@
         return (uint8_t)faad_getbits(ld, 1 DEBUGVAR(print,var,dbg));
 
     ld->bits_left--;
-    r = (uint8_t)((ld->bufa >> ld->bits_left) & 1);
+    r = (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.58 2003/07/07 21:11:18 menno Exp $
+** $Id: decoder.c,v 1.59 2003/07/08 13:45:45 menno Exp $
 **/
 
 #include "common.h"
@@ -367,6 +367,130 @@
     if (hDecoder) free(hDecoder);
 }
 
+void create_channel_config(faacDecHandle hDecoder, faacDecFrameInfo *hInfo)
+{
+    hInfo->num_front_channels = 0;
+    hInfo->num_side_channels = 0;
+    hInfo->num_back_channels = 0;
+    hInfo->num_lfe_channels = 0;
+    memset(hInfo->channel_position, 0, MAX_CHANNELS*sizeof(uint8_t));
+
+    /* check if there is a PCE */
+    if (hDecoder->pce_set)
+    {
+        uint8_t i, chpos = 0;
+        uint8_t chdir, back_center = 0;
+
+        hInfo->num_front_channels = hDecoder->pce.num_front_channels;
+        hInfo->num_side_channels = hDecoder->pce.num_side_channels;
+        hInfo->num_back_channels = hDecoder->pce.num_back_channels;
+        hInfo->num_lfe_channels = hDecoder->pce.num_lfe_channels;
+
+        chdir = hInfo->num_front_channels;
+        if (chdir & 1)
+        {
+            hInfo->channel_position[chpos++] = FRONT_CHANNEL_CENTER;
+            chdir--;
+        }
+        for (i = 0; i < chdir; i += 2)
+        {
+            hInfo->channel_position[chpos++] = FRONT_CHANNEL_LEFT;
+            hInfo->channel_position[chpos++] = FRONT_CHANNEL_RIGHT;
+        }
+
+        for (i = 0; i < hInfo->num_side_channels; i += 2)
+        {
+            hInfo->channel_position[chpos++] = SIDE_CHANNEL_LEFT;
+            hInfo->channel_position[chpos++] = SIDE_CHANNEL_RIGHT;
+        }
+
+        chdir = hInfo->num_back_channels;
+        if (chdir & 1)
+        {
+            back_center = 1;
+            chdir--;
+        }
+        for (i = 0; i < chdir; i += 2)
+        {
+            hInfo->channel_position[chpos++] = BACK_CHANNEL_LEFT;
+            hInfo->channel_position[chpos++] = BACK_CHANNEL_RIGHT;
+        }
+        if (back_center)
+        {
+            hInfo->channel_position[chpos++] = BACK_CHANNEL_CENTER;
+        }
+
+        for (i = 0; i < hInfo->num_lfe_channels; i++)
+        {
+            hInfo->channel_position[chpos++] = LFE_CHANNEL;
+        }
+
+    } else {
+        switch (hDecoder->channelConfiguration)
+        {
+        case 1:
+            hInfo->num_front_channels = 1;
+            hInfo->channel_position[0] = FRONT_CHANNEL_CENTER;
+            break;
+        case 2:
+            hInfo->num_front_channels = 2;
+            hInfo->channel_position[0] = FRONT_CHANNEL_LEFT;
+            hInfo->channel_position[1] = FRONT_CHANNEL_RIGHT;
+            break;
+        case 3:
+            hInfo->num_front_channels = 3;
+            hInfo->channel_position[0] = FRONT_CHANNEL_CENTER;
+            hInfo->channel_position[1] = FRONT_CHANNEL_LEFT;
+            hInfo->channel_position[2] = FRONT_CHANNEL_RIGHT;
+            break;
+        case 4:
+            hInfo->num_front_channels = 3;
+            hInfo->num_back_channels = 1;
+            hInfo->channel_position[0] = FRONT_CHANNEL_CENTER;
+            hInfo->channel_position[1] = FRONT_CHANNEL_LEFT;
+            hInfo->channel_position[2] = FRONT_CHANNEL_RIGHT;
+            hInfo->channel_position[3] = BACK_CHANNEL_CENTER;
+            break;
+        case 5:
+            hInfo->num_front_channels = 3;
+            hInfo->num_back_channels = 2;
+            hInfo->channel_position[0] = FRONT_CHANNEL_CENTER;
+            hInfo->channel_position[1] = FRONT_CHANNEL_LEFT;
+            hInfo->channel_position[2] = FRONT_CHANNEL_RIGHT;
+            hInfo->channel_position[3] = BACK_CHANNEL_LEFT;
+            hInfo->channel_position[4] = BACK_CHANNEL_RIGHT;
+            break;
+        case 6:
+            hInfo->num_front_channels = 3;
+            hInfo->num_back_channels = 2;
+            hInfo->num_lfe_channels = 1;
+            hInfo->channel_position[0] = FRONT_CHANNEL_CENTER;
+            hInfo->channel_position[1] = FRONT_CHANNEL_LEFT;
+            hInfo->channel_position[2] = FRONT_CHANNEL_RIGHT;
+            hInfo->channel_position[3] = BACK_CHANNEL_LEFT;
+            hInfo->channel_position[4] = BACK_CHANNEL_RIGHT;
+            hInfo->channel_position[5] = LFE_CHANNEL;
+            break;
+        case 7:
+            hInfo->num_front_channels = 3;
+            hInfo->num_side_channels = 2;
+            hInfo->num_back_channels = 2;
+            hInfo->num_lfe_channels = 1;
+            hInfo->channel_position[0] = FRONT_CHANNEL_CENTER;
+            hInfo->channel_position[1] = FRONT_CHANNEL_LEFT;
+            hInfo->channel_position[2] = FRONT_CHANNEL_RIGHT;
+            hInfo->channel_position[3] = SIDE_CHANNEL_LEFT;
+            hInfo->channel_position[4] = SIDE_CHANNEL_RIGHT;
+            hInfo->channel_position[5] = BACK_CHANNEL_LEFT;
+            hInfo->channel_position[6] = BACK_CHANNEL_RIGHT;
+            hInfo->channel_position[7] = LFE_CHANNEL;
+            break;
+        default: /* channelConfiguration == 0 || channelConfiguration > 7 */
+            break;
+        }
+    }
+}
+
 void* FAADAPI faacDecDecode(faacDecHandle hDecoder,
                             faacDecFrameInfo *hInfo,
                             uint8_t *buffer, uint32_t buffer_size)
@@ -406,8 +530,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];
@@ -450,7 +574,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;
@@ -470,6 +594,20 @@
     if (ld) free(ld);
     ld = NULL;
 
+    if (!hDecoder->adts_header_present && !hDecoder->adif_header_present)
+    {
+        if (channels != hDecoder->channelConfiguration)
+            hDecoder->channelConfiguration = channels;
+
+        if (channels == 8) /* 7.1 */
+            hDecoder->channelConfiguration = 7;
+        if (channels == 7) /* not a standard channelConfiguration */
+            hDecoder->channelConfiguration = 0;
+    }
+
+    /* Make a channel configuration based on either a PCE or a channelConfiguration */
+    create_channel_config(hDecoder, hInfo);
+
     /* number of samples in this frame */
     hInfo->samples = frame_len*channels;
     /* number of channels in this frame */
@@ -683,8 +821,8 @@
 #endif
     }
 
-    sample_buffer = output_to_PCM(time_out, sample_buffer, channels,
-        frame_len, outputFormat);
+    sample_buffer = output_to_PCM(hDecoder, time_out, sample_buffer,
+        channels, frame_len, outputFormat);
 
     hDecoder->frame++;
 #ifdef LD_DEC
--- 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.23 2003/07/07 21:11:18 menno Exp $
+** $Id: decoder.h,v 1.24 2003/07/08 13:45:45 menno Exp $
 **/
 
 #ifndef __DECODER_H__
@@ -65,7 +65,6 @@
 #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)
--- 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.17 2003/07/07 21:11:18 menno Exp $
+** $Id: output.c,v 1.18 2003/07/08 13:45:45 menno Exp $
 **/
 
 #include "common.h"
@@ -44,11 +44,13 @@
 dither_t Dither;
 double doubletmp;
 
-void* output_to_PCM(real_t **input, void *sample_buffer, uint8_t channels,
+void* output_to_PCM(faacDecHandle hDecoder,
+                    real_t **input, void *sample_buffer, uint8_t channels,
                     uint16_t frame_len, uint8_t format)
 {
     uint8_t ch;
     uint16_t i, j = 0;
+    uint8_t internal_channel;
 
     int16_t   *short_sample_buffer = (int16_t*)sample_buffer;
     int32_t   *int_sample_buffer = (int32_t*)sample_buffer;
@@ -58,6 +60,13 @@
     /* Copy output to a standard PCM buffer */
     for (ch = 0; ch < channels; ch++)
     {
+        if (hDecoder->pce_set)
+        {
+            internal_channel = hDecoder->internal_channel[ch];
+        } else {
+            internal_channel = ch;
+        }
+
         switch (format)
         {
         case FAAD_FMT_16BIT:
@@ -66,7 +75,7 @@
                 int32_t tmp;
                 real_t ftemp;
 
-                ftemp = input[ch][i] + 0xff8000;
+                ftemp = input[internal_channel][i] + 0xff8000;
                 ftol(ftemp, short_sample_buffer[(i*channels)+ch]);
             }
             break;
@@ -73,7 +82,7 @@
         case FAAD_FMT_16BIT_DITHER:
             for(i = 0; i < frame_len; i++, j++)
             {
-                double Sum = input[ch][i] * 65535.f;
+                double Sum = input[internal_channel][i] * 65535.f;
                 int64_t val;
                 if(j > 31)
                    j = 0;
@@ -90,7 +99,7 @@
         case FAAD_FMT_16BIT_H_SHAPE:
             for(i = 0; i < frame_len; i++, j++)
             {
-                double Sum = input[ch][i] * 65535.f;
+                double Sum = input[internal_channel][i] * 65535.f;
                 int64_t val;
                 if(j > 31)
                    j = 0;
@@ -105,33 +114,33 @@
         case FAAD_FMT_24BIT:
             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);
-                int_sample_buffer[(i*channels)+ch] = ROUND(input[ch][i]*(1<<8));
+                if (input[internal_channel][i] > (1<<15)-1)
+                    input[internal_channel][i] = (1<<15)-1;
+                else if (input[internal_channel][i] < -(1<<15))
+                    input[internal_channel][i] = -(1<<15);
+                int_sample_buffer[(i*channels)+ch] = ROUND(input[internal_channel][i]*(1<<8));
             }
             break;
         case FAAD_FMT_32BIT:
             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);
-                int_sample_buffer[(i*channels)+ch] = ROUND32(input[ch][i]*(1<<16));
+                if (input[internal_channel][i] > (1<<15)-1)
+                    input[internal_channel][i] = (1<<15)-1;
+                else if (input[internal_channel][i] < -(1<<15))
+                    input[internal_channel][i] = -(1<<15);
+                int_sample_buffer[(i*channels)+ch] = ROUND32(input[internal_channel][i]*(1<<16));
             }
             break;
         case FAAD_FMT_FLOAT:
             for(i = 0; i < frame_len; i++)
             {
-                float_sample_buffer[(i*channels)+ch] = input[ch][i]*FLOAT_SCALE;
+                float_sample_buffer[(i*channels)+ch] = input[internal_channel][i]*FLOAT_SCALE;
             }
             break;
         case FAAD_FMT_DOUBLE:
             for(i = 0; i < frame_len; i++)
             {
-                double_sample_buffer[(i*channels)+ch] = (double)input[ch][i]*FLOAT_SCALE;
+                double_sample_buffer[(i*channels)+ch] = (double)input[internal_channel][i]*FLOAT_SCALE;
             }
             break;
         }
@@ -170,7 +179,8 @@
 
 #else
 
-void* output_to_PCM(real_t **input, void *sample_buffer, uint8_t channels,
+void* output_to_PCM(faacDecHandle hDecoder,
+                    real_t **input, void *sample_buffer, uint8_t channels,
                     uint16_t frame_len, uint8_t format)
 {
     uint8_t ch;
--- a/libfaad/output.h
+++ b/libfaad/output.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: output.h,v 1.6 2002/08/26 19:08:39 menno Exp $
+** $Id: output.h,v 1.7 2003/07/08 13:45:45 menno Exp $
 **/
 
 #ifndef __OUTPUT_H__
@@ -26,7 +26,8 @@
 extern "C" {
 #endif
 
-void* output_to_PCM(real_t **input,
+void* output_to_PCM(faacDecHandle hDecoder,
+                    real_t **input,
                     void *samplebuffer,
                     uint8_t channels,
                     uint16_t frame_len,
--- 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.6 2003/07/07 21:11:18 menno Exp $
+** $Id: structs.h,v 1.7 2003/07/08 13:45:45 menno Exp $
 **/
 
 #ifndef __STRUCTS_H__
@@ -121,6 +121,14 @@
 
     uint8_t comment_field_bytes;
     uint8_t comment_field_data[257];
+
+    /* extra added values */
+    uint8_t num_front_channels;
+    uint8_t num_side_channels;
+    uint8_t num_back_channels;
+    uint8_t num_lfe_channels;
+    uint8_t sce_channel[16];
+    uint8_t cpe_channel[16];
 } program_config;
 
 typedef struct
@@ -317,7 +325,11 @@
     uint32_t samplerate;
 
     /* multichannel configuration */
-    uint8_t channel_config[64];
+    uint8_t num_front_channels;
+    uint8_t num_side_channels;
+    uint8_t num_back_channels;
+    uint8_t num_lfe_channels;
+    uint8_t channel_position[MAX_CHANNELS];
 } faacDecFrameInfo;
 
 typedef struct
@@ -373,6 +385,7 @@
     uint8_t pce_set;
     program_config pce;
     uint8_t channel_element[MAX_CHANNELS];
+    uint8_t internal_channel[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.46 2003/07/07 21:11:18 menno Exp $
+** $Id: syntax.c,v 1.47 2003/07/08 13:45:45 menno Exp $
 **/
 
 /*
@@ -65,10 +65,8 @@
         program_config_element(&pce, ld);
         mp4ASC->channelsConfiguration = pce.channels;
 
-        /*
         if (pce.num_valid_cc_elements)
             return -3;
-        */
     }
 
 #ifdef ERROR_RESILIENCE
@@ -103,6 +101,8 @@
 {
     uint8_t i;
 
+    memset(pce, 0, sizeof(program_config));
+
     pce->channels = 0;
 
     pce->element_instance_tag = (uint8_t)faad_getbits(ld, 4
@@ -153,72 +153,80 @@
 
     for (i = 0; i < pce->num_front_channel_elements; i++)
     {
-        if ((pce->front_element_is_cpe[i] = faad_get1bit(ld
-            DEBUGVAR(1,26,"program_config_element(): front_element_is_cpe"))) & 1)
+        pce->front_element_is_cpe[i] = faad_get1bit(ld
+            DEBUGVAR(1,26,"program_config_element(): front_element_is_cpe"));
+        pce->front_element_tag_select[i] = (uint8_t)faad_getbits(ld, 4
+            DEBUGVAR(1,27,"program_config_element(): front_element_tag_select"));
+
+        if (pce->front_element_is_cpe[i] & 1)
         {
-//            printf("CPE ");
+            pce->cpe_channel[pce->front_element_tag_select[i]] = pce->channels;
+            pce->num_front_channels += 2;
             pce->channels += 2;
         } else {
-//            printf("SCE ");
+            pce->sce_channel[pce->front_element_tag_select[i]] = pce->channels;
+            pce->num_front_channels++;
             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++)
     {
-        if ((pce->side_element_is_cpe[i] = faad_get1bit(ld
-            DEBUGVAR(1,28,"program_config_element(): side_element_is_cpe"))) & 1)
+        pce->side_element_is_cpe[i] = faad_get1bit(ld
+            DEBUGVAR(1,28,"program_config_element(): side_element_is_cpe"));
+        pce->side_element_tag_select[i] = (uint8_t)faad_getbits(ld, 4
+            DEBUGVAR(1,29,"program_config_element(): side_element_tag_select"));
+
+        if (pce->side_element_is_cpe[i] & 1)
         {
-//            printf("CPE ");
+            pce->cpe_channel[pce->side_element_tag_select[i]] = pce->channels;
+            pce->num_side_channels += 2;
             pce->channels += 2;
         } else {
-//            printf("SCE ");
+            pce->sce_channel[pce->side_element_tag_select[i]] = pce->channels;
+            pce->num_side_channels++;
             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++)
     {
-        if ((pce->back_element_is_cpe[i] = faad_get1bit(ld
-            DEBUGVAR(1,30,"program_config_element(): back_element_is_cpe"))) & 1)
+        pce->back_element_is_cpe[i] = faad_get1bit(ld
+            DEBUGVAR(1,30,"program_config_element(): back_element_is_cpe"));
+        pce->back_element_tag_select[i] = (uint8_t)faad_getbits(ld, 4
+            DEBUGVAR(1,31,"program_config_element(): back_element_tag_select"));
+
+        if (pce->back_element_is_cpe[i] & 1)
         {
-//            printf("CPE ");
+            pce->cpe_channel[pce->back_element_tag_select[i]] = pce->channels;
             pce->channels += 2;
+            pce->num_back_channels += 2;
         } else {
-//            printf("SCE ");
+            pce->sce_channel[pce->back_element_tag_select[i]] = pce->channels;
+            pce->num_back_channels++;
             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++)
     {
-        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]);
+        pce->sce_channel[pce->lfe_element_tag_select[i]] = pce->channels;
+        pce->num_lfe_channels++;
+        pce->channels++;
     }
 
     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
@@ -271,6 +279,9 @@
     hInfo->error = single_lfe_channel_element(hDecoder, ele,
         ld, spec_data[channels]);
 
+    if (hDecoder->pce_set)
+        hDecoder->internal_channel[hDecoder->pce.sce_channel[ele->element_instance_tag]] = channels;
+
     if (id_syn_ele == ID_SCE)
         hDecoder->channel_element[channels] = hDecoder->fr_ch_ele;
     else /* LFE */
@@ -315,6 +326,12 @@
     hInfo->error = channel_pair_element(hDecoder, ele,
         ld, spec_data[channels], spec_data[channels+1]);
 
+    if (hDecoder->pce_set)
+    {
+        hDecoder->internal_channel[hDecoder->pce.cpe_channel[ele->element_instance_tag]] = channels;
+        hDecoder->internal_channel[hDecoder->pce.cpe_channel[ele->element_instance_tag]+1] = channels+1;
+    }
+
     hDecoder->channel_element[channels] = hDecoder->fr_ch_ele;
     hDecoder->channel_element[channels+1] = hDecoder->fr_ch_ele;
 
@@ -816,7 +833,7 @@
     memset(&el_empty, 0, sizeof(element));
     memset(&ics_empty, 0, sizeof(ic_stream));
 
-    faad_getbits(ld, LEN_TAG
+    c = faad_getbits(ld, LEN_TAG
         DEBUGVAR(1,900,"coupling_channel_element(): element_instance_tag"));
 
     ind_sw_cce_flag = faad_get1bit(ld