shithub: aacdec

Download patch

ref: 9596ecdf5d384c896dbb32e13eb9d3856b9d09f8
parent: 401e13ef1ffdaff4ca970bfc0b7ca4c31d37b7f1
author: menno <menno>
date: Wed Jul 9 09:55:59 EDT 2003

Channel downmixing implemented: 5.1/5 ch -> 2 ch

--- 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.39 2003/07/09 11:53:07 menno Exp $
+** $Id: main.c,v 1.40 2003/07/09 13:55:59 menno Exp $
 **/
 
 #ifdef _WIN32
@@ -239,6 +239,7 @@
     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, " -d    Down matrix 5.1 to 2 channels\n");
     fprintf(stdout, " -w    Write output to stdio instead of a file.\n");
     fprintf(stdout, "Example:\n");
     fprintf(stdout, "       faad infile.aac\n");
@@ -250,7 +251,7 @@
 
 int decodeAACfile(char *aacfile, char *sndfile, int to_stdout,
                   int def_srate, int object_type, int outputFormat, int fileType,
-                  int infoOnly)
+                  int downMatrix, int infoOnly)
 {
     int tagsize;
     unsigned long samplerate;
@@ -324,7 +325,7 @@
         config->defSampleRate = def_srate;
     config->defObjectType = object_type;
     config->outputFormat = outputFormat;
-
+    config->downMatrix = downMatrix;
     faacDecSetConfiguration(hDecoder, config);
 
     /* get AAC infos for printing */
@@ -523,7 +524,7 @@
 };
 
 int decodeMP4file(char *mp4file, char *sndfile, int to_stdout,
-                  int outputFormat, int fileType, int infoOnly)
+                  int outputFormat, int fileType, int downMatrix, int infoOnly)
 {
     int track;
     unsigned int tracks;
@@ -553,6 +554,7 @@
     /* Set configuration */
     config = faacDecGetCurrentConfiguration(hDecoder);
     config->outputFormat = outputFormat;
+    config->downMatrix = downMatrix;
     faacDecSetConfiguration(hDecoder, config);
 
     infile = MP4Read(mp4file, 0);
@@ -705,6 +707,7 @@
     int writeToStdio = 0;
     int object_type = LC;
     int def_srate = 0;
+    int downMatrix = 0;
     int format = 1;
     int outputFormat = FAAD_FMT_16BIT;
     int outfile_set = 0;
@@ -747,12 +750,13 @@
             { "bits",       0, 0, 'b' },
             { "samplerate", 0, 0, 's' },
             { "objecttype", 0, 0, 'l' },
+            { "downmix",    0, 0, 'd' },
             { "info",       0, 0, 'i' },
             { "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:wdhi",
             long_options, &option_index);
 
         if (c == -1)
@@ -816,6 +820,9 @@
                 }
             }
             break;
+        case 'd':
+            downMatrix = 1;
+            break;
         case 'w':
             writeToStdio = 1;
             break;
@@ -871,10 +878,10 @@
     if (mp4file)
     {
         result = decodeMP4file(aacFileName, audioFileName, writeToStdio,
-            outputFormat, format, infoOnly);
+            outputFormat, format, downMatrix, infoOnly);
     } else {
         result = decodeAACfile(aacFileName, audioFileName, writeToStdio,
-            def_srate, object_type, outputFormat, format, infoOnly);
+            def_srate, object_type, outputFormat, format, downMatrix, infoOnly);
     }
 
 
--- 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.24 2003/07/09 11:53:07 menno Exp $
+** $Id: faad.h,v 1.25 2003/07/09 13:55:59 menno Exp $
 **/
 
 #ifndef __AACDEC_H__
@@ -118,6 +118,7 @@
     unsigned char defObjectType;
     unsigned long defSampleRate;
     unsigned char outputFormat;
+    unsigned char downMatrix;
 } faacDecConfiguration, *faacDecConfigurationPtr;
 
 typedef struct faacDecFrameInfo
--- 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.60 2003/07/09 11:53:07 menno Exp $
+** $Id: decoder.c,v 1.61 2003/07/09 13:55:59 menno Exp $
 **/
 
 #include "common.h"
@@ -146,6 +146,7 @@
     hDecoder->config.defObjectType = config->defObjectType;
     hDecoder->config.defSampleRate = config->defSampleRate;
     hDecoder->config.outputFormat  = config->outputFormat;
+    hDecoder->config.downMatrix    = config->downMatrix;
 
     /* OK */
     return 1;
@@ -382,6 +383,14 @@
     hInfo->num_lfe_channels = 0;
     memset(hInfo->channel_position, 0, MAX_CHANNELS*sizeof(uint8_t));
 
+    if (hDecoder->downMatrix)
+    {
+        hInfo->num_front_channels = 2;
+        hInfo->channel_position[0] = FRONT_CHANNEL_LEFT;
+        hInfo->channel_position[1] = FRONT_CHANNEL_RIGHT;
+        return;
+    }
+
     /* check if there is a PCE */
     if (hDecoder->pce_set)
     {
@@ -499,7 +508,6 @@
                 if (ch & 1) /* there's either a center front or a center back channel */
                 {
                     uint8_t ch1 = (ch-1)/2;
-                    _assert(!(ch1&1));
                     if (hDecoder->first_syn_ele == ID_SCE)
                     {
                         hInfo->num_front_channels = ch1 + 1;
@@ -580,6 +588,7 @@
     uint8_t ch;
     adts_header adts;
     uint8_t channels = 0, ch_ele = 0;
+    uint8_t output_channels = 0;
     bitfile *ld = (bitfile*)malloc(sizeof(bitfile));
 
     /* local copys of globals */
@@ -611,8 +620,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];
@@ -655,7 +664,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;
@@ -686,13 +695,21 @@
             hDecoder->channelConfiguration = 0;
     }
 
+    if ((channels == 5 || channels == 6) && hDecoder->config.downMatrix)
+    {
+        hDecoder->downMatrix = 1;
+        output_channels = 2;
+    } else {
+        output_channels = channels;
+    }
+
     /* 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;
+    hInfo->samples = frame_len*output_channels;
     /* number of channels in this frame */
-    hInfo->channels = channels;
+    hInfo->channels = output_channels;
     /* samplerate */
     hInfo->samplerate = sample_rates[hDecoder->sf_index];
 
@@ -706,9 +723,9 @@
     if (hDecoder->sample_buffer == NULL)
     {
         if (hDecoder->config.outputFormat == FAAD_FMT_DOUBLE)
-            hDecoder->sample_buffer = malloc(frame_len*channels*sizeof(double));
+            hDecoder->sample_buffer = malloc(frame_len*output_channels*sizeof(double));
         else
-            hDecoder->sample_buffer = malloc(frame_len*channels*sizeof(real_t));
+            hDecoder->sample_buffer = malloc(frame_len*output_channels*sizeof(real_t));
     }
 
     sample_buffer = hDecoder->sample_buffer;
@@ -903,7 +920,7 @@
     }
 
     sample_buffer = output_to_PCM(hDecoder, time_out, sample_buffer,
-        channels, frame_len, outputFormat);
+        output_channels, frame_len, outputFormat);
 
     hDecoder->frame++;
 #ifdef LD_DEC
--- 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.18 2003/07/08 13:45:45 menno Exp $
+** $Id: output.c,v 1.19 2003/07/09 13:55:59 menno Exp $
 **/
 
 #include "common.h"
@@ -44,6 +44,28 @@
 dither_t Dither;
 double doubletmp;
 
+#define DM_MUL (1./(1.+sqrt(2.)))
+
+static INLINE real_t get_sample(real_t **input, uint8_t channel, uint16_t sample,
+                                uint8_t downMatrix, uint8_t *internal_channel)
+{
+    if (downMatrix)
+    {
+        if (channel == 0)
+        {
+            return DM_MUL * (input[internal_channel[1]][sample] +
+                input[internal_channel[0]][sample]/sqrt(2.) +
+                input[internal_channel[3]][sample]/sqrt(2.));
+        } else {
+            return DM_MUL * (input[internal_channel[2]][sample] +
+                input[internal_channel[0]][sample]/sqrt(2.) +
+                input[internal_channel[4]][sample]/sqrt(2.));
+        }
+    } else {
+        return input[internal_channel[channel]][sample];
+    }
+}
+
 void* output_to_PCM(faacDecHandle hDecoder,
                     real_t **input, void *sample_buffer, uint8_t channels,
                     uint16_t frame_len, uint8_t format)
@@ -60,12 +82,7 @@
     /* 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;
-        }
+        internal_channel = hDecoder->internal_channel[ch];
 
         switch (format)
         {
@@ -74,8 +91,10 @@
             {
                 int32_t tmp;
                 real_t ftemp;
+                //real_t inp = input[internal_channel][i];
+                real_t inp = get_sample(input, ch, i, hDecoder->downMatrix, hDecoder->internal_channel);
 
-                ftemp = input[internal_channel][i] + 0xff8000;
+                ftemp = inp + 0xff8000;
                 ftol(ftemp, short_sample_buffer[(i*channels)+ch]);
             }
             break;
@@ -82,7 +101,8 @@
         case FAAD_FMT_16BIT_DITHER:
             for(i = 0; i < frame_len; i++, j++)
             {
-                double Sum = input[internal_channel][i] * 65535.f;
+                real_t inp = input[internal_channel][i];
+                double Sum = inp * 65535.f;
                 int64_t val;
                 if(j > 31)
                    j = 0;
@@ -99,7 +119,8 @@
         case FAAD_FMT_16BIT_H_SHAPE:
             for(i = 0; i < frame_len; i++, j++)
             {
-                double Sum = input[internal_channel][i] * 65535.f;
+                real_t inp = input[internal_channel][i];
+                double Sum = inp * 65535.f;
                 int64_t val;
                 if(j > 31)
                    j = 0;
@@ -114,33 +135,37 @@
         case FAAD_FMT_24BIT:
             for(i = 0; i < frame_len; i++)
             {
-                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));
+                real_t inp = input[internal_channel][i];
+                if (inp > (1<<15)-1)
+                    inp = (1<<15)-1;
+                else if (inp < -(1<<15))
+                    inp = -(1<<15);
+                int_sample_buffer[(i*channels)+ch] = ROUND(inp*(1<<8));
             }
             break;
         case FAAD_FMT_32BIT:
             for(i = 0; i < frame_len; i++)
             {
-                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));
+                real_t inp = input[internal_channel][i];
+                if (inp > (1<<15)-1)
+                    inp = (1<<15)-1;
+                else if (inp < -(1<<15))
+                    inp = -(1<<15);
+                int_sample_buffer[(i*channels)+ch] = ROUND32(inp*(1<<16));
             }
             break;
         case FAAD_FMT_FLOAT:
             for(i = 0; i < frame_len; i++)
             {
-                float_sample_buffer[(i*channels)+ch] = input[internal_channel][i]*FLOAT_SCALE;
+                real_t inp = input[internal_channel][i];
+                float_sample_buffer[(i*channels)+ch] = inp*FLOAT_SCALE;
             }
             break;
         case FAAD_FMT_DOUBLE:
             for(i = 0; i < frame_len; i++)
             {
-                double_sample_buffer[(i*channels)+ch] = (double)input[internal_channel][i]*FLOAT_SCALE;
+                real_t inp = input[internal_channel][i];
+                double_sample_buffer[(i*channels)+ch] = (double)inp*FLOAT_SCALE;
             }
             break;
         }
--- 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.8 2003/07/09 11:53:07 menno Exp $
+** $Id: structs.h,v 1.9 2003/07/09 13:55:59 menno Exp $
 **/
 
 #ifndef __STRUCTS_H__
@@ -314,6 +314,7 @@
     uint8_t defObjectType;
     uint32_t defSampleRate;
     uint8_t outputFormat;
+    uint8_t downMatrix;
 } faacDecConfiguration, *faacDecConfigurationPtr;
 
 typedef struct faacDecFrameInfo
@@ -348,6 +349,7 @@
 
     uint32_t frame;
 
+    uint8_t downMatrix;
     uint8_t first_syn_ele;
     uint8_t last_syn_ele;
     uint8_t has_lfe;
--- 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.49 2003/07/09 12:33:08 menno Exp $
+** $Id: syntax.c,v 1.50 2003/07/09 13:55:59 menno Exp $
 **/
 
 /*
@@ -284,6 +284,8 @@
 
     if (hDecoder->pce_set)
         hDecoder->internal_channel[hDecoder->pce.sce_channel[ele->element_instance_tag]] = channels;
+    else
+        hDecoder->internal_channel[channels] = channels;
 
     if (id_syn_ele == ID_SCE)
         hDecoder->channel_element[channels] = hDecoder->fr_ch_ele;
@@ -333,6 +335,9 @@
     {
         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;
+    } else {
+        hDecoder->internal_channel[channels] = channels;
+        hDecoder->internal_channel[channels+1] = channels+1;
     }
 
     hDecoder->channel_element[channels] = hDecoder->fr_ch_ele;