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;