diff -Naur faac-1.28.old/frontend/main.c faac-1.28.new/frontend/main.c --- faac-1.28.old/frontend/main.c 2009-01-24 02:10:20.000000000 +0100 +++ faac-1.28.new/frontend/main.c 2012-08-06 21:15:34.000000000 +0200 @@ -858,7 +858,7 @@ break; } if (infile->channels >= 6) - myFormat->useLfe = 1; + myFormat->numLFEChannels = 1; myFormat->allowMidside = useMidSide; if (bitRate) myFormat->bitRate = bitRate / infile->channels; diff -Naur faac-1.28.old/include/faaccfg.h faac-1.28.new/include/faaccfg.h --- faac-1.28.old/include/faaccfg.h 2004-07-04 14:12:05.000000000 +0200 +++ faac-1.28.new/include/faaccfg.h 2012-08-06 21:15:34.000000000 +0200 @@ -66,8 +66,14 @@ /* Allow mid/side coding */ unsigned int allowMidside; - /* Use one of the channels as LFE channel */ - unsigned int useLfe; + /* Channel configuration */ + unsigned int channelConfiguration; + + /* Number of front, side, back & LFE channels */ + unsigned int numFrontChannels; + unsigned int numSideChannels; + unsigned int numBackChannels; + unsigned int numLFEChannels; /* Use Temporal Noise Shaping */ unsigned int useTns; diff -Naur faac-1.28.old/libfaac/bitstream.c faac-1.28.new/libfaac/bitstream.c --- faac-1.28.old/libfaac/bitstream.c 2007-06-05 20:59:47.000000000 +0200 +++ faac-1.28.new/libfaac/bitstream.c 2012-08-06 21:15:34.000000000 +0200 @@ -1032,6 +1032,219 @@ return j; } +/* write a program_config_element() */ +int WritePCE(faacEncHandle hEncoder, + BitStream *bitStream, + int byte_alignment, + int instance_tag, + int writeFlag) +{ + int i; + int bits = 0; + + /* we can have up to 29 full-bandwidth channels of each type: + * 4 bits -> 0 - 15 elements, 14 CPEs (28 channels) and 1 SCE (1 channel) + * we can have up to 3 LFE channels: + * 2 bits -> 0 - 3 elements, 3 LFEs (1 channel) */ + if (hEncoder->config.numFrontChannels > 29) { + fprintf(stderr, "WritePCE: too many front channels (%u)\n", + hEncoder->config.numFrontChannels); + return 0; + } + if (hEncoder->config.numSideChannels > 29) { + fprintf(stderr, "WritePCE: too many side channels (%u)\n", + hEncoder->config.numSideChannels); + return 0; + } + if (hEncoder->config.numBackChannels > 29) { + fprintf(stderr, "WritePCE: too many back channels (%u)\n", + hEncoder->config.numBackChannels); + return 0; + } + if (hEncoder->config.numLFEChannels > 3) { + fprintf(stderr, "WritePCE: too many LFE channels (%u)\n", + hEncoder->config.numLFEChannels); + return 0; + } + /* program_config_element() shall be used only for the audio object types: + * AAC main, AAC SSR, AAC LC and AAC LTP */ + if (hEncoder->config.aacObjectType > 4) { + fprintf(stderr, "WritePCE: unsupported AudioObjectType %u", + hEncoder->config.aacObjectType); + return 0; + } + + /* Determine the channel configuration (see GetChannelInfo) */ + int sceTag = 0; + int cpeTag = 0; + int lfeTag = 0; + int num_front_channel_elements = 0; + int front_element_is_cpe[15] = { 0 }; + int front_element_tag_select[15] = { 0 }; + int num_side_channel_elements = 0; + int side_element_is_cpe[15] = { 0 }; + int side_element_tag_select[15] = { 0 }; + int num_back_channel_elements = 0; + int back_element_is_cpe[15] = { 0 }; + int back_element_tag_select[15] = { 0 }; + int num_lfe_channel_elements = 0; + int lfe_element_tag_select[3] = { 0 }; + // Front channels + i = hEncoder->config.numFrontChannels; + if (i % 2) { + front_element_is_cpe[num_front_channel_elements] = 0; + front_element_tag_select[num_front_channel_elements] = sceTag; + num_front_channel_elements++; + sceTag++; + i--; + } + while (i) { + front_element_is_cpe[num_front_channel_elements] = 1; + front_element_tag_select[num_front_channel_elements] = cpeTag; + num_front_channel_elements++; + cpeTag++; + i -= 2; + } + // Side channels + i = hEncoder->config.numSideChannels; + while (i > 1) { + side_element_is_cpe[num_side_channel_elements] = 1; + side_element_tag_select[num_side_channel_elements] = cpeTag; + num_side_channel_elements++; + cpeTag++; + i -= 2; + } + if (i) { + side_element_is_cpe[num_side_channel_elements] = 0; + side_element_tag_select[num_side_channel_elements] = sceTag; + num_side_channel_elements++; + sceTag++; + i--; + } + // Back channels + i = hEncoder->config.numBackChannels; + while (i > 1) { + back_element_is_cpe[num_back_channel_elements] = 1; + back_element_tag_select[num_back_channel_elements] = cpeTag; + num_back_channel_elements++; + cpeTag++; + i -= 2; + } + if (i) { + back_element_is_cpe[num_back_channel_elements] = 0; + back_element_tag_select[num_back_channel_elements] = sceTag; + num_back_channel_elements++; + sceTag++; + i--; + } + // LFE channels + i = hEncoder->config.numLFEChannels; + while (i) { + lfe_element_tag_select[num_lfe_channel_elements] = lfeTag; + num_lfe_channel_elements++; + lfeTag++; + i--; + } + + /* element_instance_tag */ + if (writeFlag) + PutBit(bitStream, instance_tag, 4); + bits =+ 4; + + /* object_type */ + if (writeFlag) + PutBit(bitStream, hEncoder->config.aacObjectType - 1, 2); + bits += 2; + + /* sampling_frequency_index */ + if (writeFlag) + PutBit(bitStream, hEncoder->sampleRateIdx, 4); + bits += 4; + + /* num_front_channel_elements */ + if (writeFlag) + PutBit(bitStream, num_front_channel_elements, 4); + bits += 4; + + /* num_side_channel_elements */ + if (writeFlag) + PutBit(bitStream, num_side_channel_elements, 4); + bits += 4; + + /* num_back_channel_elements */ + if (writeFlag) + PutBit(bitStream, num_back_channel_elements, 4); + bits += 4; + + /* num_lfe_channel_elements */ + if (writeFlag) + PutBit(bitStream, num_lfe_channel_elements, 2); + bits += 2; + + /* num_assoc_data_elements */ + if (writeFlag) + PutBit(bitStream, 0, 3); + bits += 3; + + /* num_valid_cc_elements */ + if (writeFlag) + PutBit(bitStream, 0, 4); + bits += 4; + + /* mono_mixdown_present */ + if (writeFlag) + PutBit(bitStream, 0, 1); + bits++; + + /* stereo_mixdown_present */ + if (writeFlag) + PutBit(bitStream, 0, 1); + bits++; + + /* matrix_mixdown_idx_present */ + if (writeFlag) + PutBit(bitStream, 0, 1); + bits++; + + /* describe the channel configuration */ + for (i = 0; i < num_front_channel_elements; i++) { + if (writeFlag) { + PutBit(bitStream, front_element_is_cpe[i], 1); + PutBit(bitStream, front_element_tag_select[i], 4); + } + bits += 5; + } + for (i = 0; i < num_side_channel_elements; i++) { + if (writeFlag) { + PutBit(bitStream, side_element_is_cpe[i], 1); + PutBit(bitStream, side_element_tag_select[i], 4); + } + bits += 5; + } + for (i = 0; i < num_back_channel_elements; i++) { + if (writeFlag) { + PutBit(bitStream, back_element_is_cpe[i], 1); + PutBit(bitStream, back_element_tag_select[i], 4); + } + bits += 5; + } + for (i = 0; i < num_lfe_channel_elements; i++) { + if (writeFlag) + PutBit(bitStream, lfe_element_tag_select[i], 4); + bits += 4; + } + + /* byte_alignment() */ + bits += ByteAlign(bitStream, writeFlag, bits + byte_alignment); + + /* comment_field_bytes */ + if (writeFlag) + PutBit(bitStream, 0, 8); + bits += 8; + + return bits; +} + #ifdef DRM /* **************************************************************************** diff -Naur faac-1.28.old/libfaac/bitstream.h faac-1.28.new/libfaac/bitstream.h --- faac-1.28.old/libfaac/bitstream.h 2004-07-04 14:10:52.000000000 +0200 +++ faac-1.28.new/libfaac/bitstream.h 2012-08-06 21:15:34.000000000 +0200 @@ -164,6 +164,13 @@ unsigned long data, int numBit); +/* write a program_config_element() */ +int WritePCE(faacEncHandle hEncoder, + BitStream *bitStream, + int byte_alignment, + int instance_tag, + int writeFlag); + #ifdef __cplusplus } #endif /* __cplusplus */ diff -Naur faac-1.28.old/libfaac/channels.c faac-1.28.new/libfaac/channels.c --- faac-1.28.old/libfaac/channels.c 2001-09-04 20:39:35.000000000 +0200 +++ faac-1.28.new/libfaac/channels.c 2012-08-06 21:15:34.000000000 +0200 @@ -28,83 +28,112 @@ #include "coder.h" #include "util.h" -/* If LFE present */ -/* Num channels # of SCE's # of CPE's #of LFE's */ -/* ============ ========== ========== ========= */ -/* 1 1 0 0 */ -/* 2 0 1 0 */ -/* 3 1 1 0 */ -/* 4 1 1 1 */ -/* 5 1 2 0 */ -/* For more than 5 channels, use the following elements: */ -/* 2*N 1 2*(N-1) 1 */ -/* 2*N+1 1 2*N 0 */ -/* */ -/* Else: */ -/* */ -/* Num channels # of SCE's # of CPE's #of LFE's */ -/* ============ ========== ========== ========= */ -/* 1 1 0 0 */ -/* 2 0 1 0 */ -/* 3 1 1 0 */ -/* 4 2 1 0 */ -/* 5 1 2 0 */ -/* For more than 5 channels, use the following elements: */ -/* 2*N 2 2*(N-1) 0 */ -/* 2*N+1 1 2*N 0 */ - -void GetChannelInfo(ChannelInfo *channelInfo, int numChannels, int useLfe) -{ - int sceTag = 0; - int lfeTag = 0; - int cpeTag = 0; - int numChannelsLeft = numChannels; +static void addSCE(ChannelInfo *channelInfo, int numChannels, int numChannelsLeft, int tag); +static void addCPE(ChannelInfo *channelInfo, int numChannels, int numChannelsLeft, int tag); +static void addLFE(ChannelInfo *channelInfo, int numChannels, int numChannelsLeft, int tag); - /* First element is sce, except for 2 channel case */ - if (numChannelsLeft != 2) { - channelInfo[numChannels-numChannelsLeft].present = 1; - channelInfo[numChannels-numChannelsLeft].tag = sceTag++; - channelInfo[numChannels-numChannelsLeft].cpe = 0; - channelInfo[numChannels-numChannelsLeft].lfe = 0; +void GetChannelInfo(ChannelInfo *channelInfo, int numFrontChannels, int numSideChannels, int numBackChannels, int numLFEChannels) +{ + int i; + int sceTag = 0; + int cpeTag = 0; + int lfeTag = 0; + int numChannels = (numFrontChannels + + numSideChannels + + numBackChannels + + numLFEChannels); + int numChannelsLeft = numChannels; + + /* Front channels */ + i = numFrontChannels; + if (i % 2) { + // Front Center + addSCE(channelInfo, numChannels, numChannelsLeft, sceTag); numChannelsLeft--; + sceTag++; + i--; + } + while (i) { + // Front Left/Right, Front Left/Right of Center, ??? + addCPE(channelInfo, numChannels, numChannelsLeft, cpeTag); + numChannelsLeft -= 2; + cpeTag++; + i -= 2; } - /* Next elements are cpe's */ - while (numChannelsLeft > 1) { - /* Left channel info */ - channelInfo[numChannels-numChannelsLeft].present = 1; - channelInfo[numChannels-numChannelsLeft].tag = cpeTag++; - channelInfo[numChannels-numChannelsLeft].cpe = 1; - channelInfo[numChannels-numChannelsLeft].common_window = 0; - channelInfo[numChannels-numChannelsLeft].ch_is_left = 1; - channelInfo[numChannels-numChannelsLeft].paired_ch = numChannels-numChannelsLeft+1; - channelInfo[numChannels-numChannelsLeft].lfe = 0; + /* Side channels */ + i = numSideChannels; + while (i > 1) { + // Surround Left/Right (if rear surrounds present), ??? + addCPE(channelInfo, numChannels, numChannelsLeft, cpeTag); + numChannelsLeft -= 2; + cpeTag++; + i -= 2; + } + if (i) { + // ??? + addSCE(channelInfo, numChannels, numChannelsLeft, sceTag); numChannelsLeft--; + sceTag++; + i--; + } - /* Right channel info */ - channelInfo[numChannels-numChannelsLeft].present = 1; - channelInfo[numChannels-numChannelsLeft].cpe = 1; - channelInfo[numChannels-numChannelsLeft].common_window = 0; - channelInfo[numChannels-numChannelsLeft].ch_is_left = 0; - channelInfo[numChannels-numChannelsLeft].paired_ch = numChannels-numChannelsLeft-1; - channelInfo[numChannels-numChannelsLeft].lfe = 0; + /* Back channels */ + i = numBackChannels; + while (i > 1) { + // Surround Left/Right (if rear surrounds absent), Rear Surround Left/Right, ??? + addCPE(channelInfo, numChannels, numChannelsLeft, cpeTag); + numChannelsLeft -= 2; + cpeTag++; + i -= 2; + } + if (i) { + // Surround Center + addSCE(channelInfo, numChannels, numChannelsLeft, sceTag); numChannelsLeft--; + sceTag++; + i--; } - /* Is there another channel left ? */ - if (numChannelsLeft) { - if (useLfe) { - channelInfo[numChannels-numChannelsLeft].present = 1; - channelInfo[numChannels-numChannelsLeft].tag = lfeTag++; - channelInfo[numChannels-numChannelsLeft].cpe = 0; - channelInfo[numChannels-numChannelsLeft].lfe = 1; - } else { - channelInfo[numChannels-numChannelsLeft].present = 1; - channelInfo[numChannels-numChannelsLeft].tag = sceTag++; - channelInfo[numChannels-numChannelsLeft].cpe = 0; - channelInfo[numChannels-numChannelsLeft].lfe = 0; - } + /* LFE channel */ + i = numLFEChannels; + while (i) { + addLFE(channelInfo, numChannels, numChannelsLeft, lfeTag); numChannelsLeft--; + lfeTag++; + i--; } } + +static void addSCE(ChannelInfo *channelInfo, int numChannels, int numChannelsLeft, int tag) { + channelInfo[numChannels-numChannelsLeft].present = 1; + channelInfo[numChannels-numChannelsLeft].cpe = 0; + channelInfo[numChannels-numChannelsLeft].lfe = 0; + channelInfo[numChannels-numChannelsLeft].tag = tag; +} + +static void addCPE(ChannelInfo *channelInfo, int numChannels, int numChannelsLeft, int tag) { + /* Left channel info */ + channelInfo[numChannels-numChannelsLeft].present = 1; + channelInfo[numChannels-numChannelsLeft].cpe = 1; + channelInfo[numChannels-numChannelsLeft].lfe = 0; + channelInfo[numChannels-numChannelsLeft].tag = tag; + channelInfo[numChannels-numChannelsLeft].ch_is_left = 1; + channelInfo[numChannels-numChannelsLeft].common_window = 0; + channelInfo[numChannels-numChannelsLeft].paired_ch = numChannels-numChannelsLeft+1; + /* Right channel info */ + channelInfo[numChannels-numChannelsLeft+1].present = 1; + channelInfo[numChannels-numChannelsLeft+1].cpe = 1; + channelInfo[numChannels-numChannelsLeft+1].lfe = 0; + channelInfo[numChannels-numChannelsLeft+1].ch_is_left = 0; + channelInfo[numChannels-numChannelsLeft+1].common_window = 0; + channelInfo[numChannels-numChannelsLeft+1].paired_ch = numChannels-numChannelsLeft; +} + +static void addLFE(ChannelInfo *channelInfo, int numChannels, int numChannelsLeft, int tag) { + channelInfo[numChannels-numChannelsLeft].present = 1; + channelInfo[numChannels-numChannelsLeft].cpe = 0; + channelInfo[numChannels-numChannelsLeft].lfe = 1; + channelInfo[numChannels-numChannelsLeft].tag = tag; +} diff -Naur faac-1.28.old/libfaac/channels.h faac-1.28.new/libfaac/channels.h --- faac-1.28.old/libfaac/channels.h 2003-06-26 21:19:41.000000000 +0200 +++ faac-1.28.new/libfaac/channels.h 2012-08-06 21:15:34.000000000 +0200 @@ -45,7 +45,7 @@ MSInfo msInfo; } ChannelInfo; -void GetChannelInfo(ChannelInfo *channelInfo, int numChannels, int useLfe); +void GetChannelInfo(ChannelInfo *channelInfo, int numFrontChannels, int numSideChannels, int numBackChannels, int numLFEChannels); #ifdef __cplusplus } diff -Naur faac-1.28.old/libfaac/frame.c faac-1.28.new/libfaac/frame.c --- faac-1.28.old/libfaac/frame.c 2004-11-17 15:26:06.000000000 +0100 +++ faac-1.28.new/libfaac/frame.c 2012-08-06 21:15:34.000000000 +0200 @@ -99,21 +99,47 @@ return -2; /* not supported */ } - *pSizeOfDecoderSpecificInfo = 2; - *ppBuffer = malloc(2); + if (hEncoder->config.channelConfiguration > 7) { + fprintf(stderr, "faacEncGetDecoderSpecificInfo: " + "invalid channel configuration %u\n", + hEncoder->config.channelConfiguration); + return -2; + } else if (hEncoder->config.channelConfiguration) { + // 16 bits + *pSizeOfDecoderSpecificInfo = 2; + } else { + // 16 bits + size of the program_config_element() + *pSizeOfDecoderSpecificInfo = 2 + (WritePCE(hEncoder, NULL, 0, 0, 0) / 8); + } - if(*ppBuffer != NULL){ + *ppBuffer = malloc(*pSizeOfDecoderSpecificInfo); + if (*ppBuffer != NULL) { memset(*ppBuffer,0,*pSizeOfDecoderSpecificInfo); pBitStream = OpenBitStream(*pSizeOfDecoderSpecificInfo, *ppBuffer); PutBit(pBitStream, hEncoder->config.aacObjectType, 5); PutBit(pBitStream, hEncoder->sampleRateIdx, 4); - PutBit(pBitStream, hEncoder->numChannels, 4); + PutBit(pBitStream, hEncoder->config.channelConfiguration, 4); + PutBit(pBitStream, 0, 1); // frameLengthFlag + PutBit(pBitStream, 0, 1); // dependsOnCoreCoder + PutBit(pBitStream, 0, 1); // extensionFlag + if (!hEncoder->config.channelConfiguration) { + /* a program_config_element() must be written */ + if (WritePCE(hEncoder, pBitStream, 0, 0, 1) <= 0) { + fprintf(stderr, + "faacEncGetDecoderSpecificInfo: WritePCE() failed!\n"); + *pSizeOfDecoderSpecificInfo = 0; + CloseBitStream(pBitStream); + free(*ppBuffer); + *ppBuffer = NULL; + return -3; + } + } CloseBitStream(pBitStream); - return 0; } else { - return -3; + *pSizeOfDecoderSpecificInfo = 0; + return -4; } } @@ -131,7 +157,6 @@ int i; hEncoder->config.allowMidside = config->allowMidside; - hEncoder->config.useLfe = config->useLfe; hEncoder->config.useTns = config->useTns; hEncoder->config.aacObjectType = config->aacObjectType; hEncoder->config.mpegVersion = config->mpegVersion; @@ -139,6 +164,77 @@ hEncoder->config.inputFormat = config->inputFormat; hEncoder->config.shortctl = config->shortctl; + if (!config->channelConfiguration) { + if (hEncoder->numChannels != (config->numFrontChannels + + config->numSideChannels + + config->numBackChannels + + config->numLFEChannels)) { + fprintf(stderr, "faacEncSetConfiguration: " + "numChannels doesn't match the custom channel configuration\n"); + return 0; + } + hEncoder->config.numFrontChannels = config->numFrontChannels; + hEncoder->config.numSideChannels = config->numSideChannels; + hEncoder->config.numBackChannels = config->numBackChannels; + hEncoder->config.numLFEChannels = config->numLFEChannels; + } else if (config->channelConfiguration > 7) { + fprintf(stderr, "faacEncSetConfiguration: " + "invalid channel configuration %u\n", + config->channelConfiguration); + return 0; + } else { + if ((config->channelConfiguration == 7 && hEncoder->numChannels != 8) || + (config->channelConfiguration != 7 && hEncoder->numChannels != config->channelConfiguration)) { + fprintf(stderr, "faacEncSetConfiguration: " + "numChannels doesn't match the channel configuration\n"); + return 0; + } + switch (config->channelConfiguration) { + case 7: + hEncoder->config.numFrontChannels = 5; + hEncoder->config.numSideChannels = 0; + hEncoder->config.numBackChannels = 2; + hEncoder->config.numLFEChannels = 1; + break; + case 6: + hEncoder->config.numFrontChannels = 3; + hEncoder->config.numSideChannels = 0; + hEncoder->config.numBackChannels = 2; + hEncoder->config.numLFEChannels = 1; + break; + case 5: + hEncoder->config.numFrontChannels = 3; + hEncoder->config.numSideChannels = 0; + hEncoder->config.numBackChannels = 2; + hEncoder->config.numLFEChannels = 0; + break; + case 4: + hEncoder->config.numFrontChannels = 3; + hEncoder->config.numSideChannels = 0; + hEncoder->config.numBackChannels = 1; + hEncoder->config.numLFEChannels = 0; + break; + case 3: + hEncoder->config.numFrontChannels = 3; + hEncoder->config.numSideChannels = 0; + hEncoder->config.numBackChannels = 0; + hEncoder->config.numLFEChannels = 0; + break; + case 2: + hEncoder->config.numFrontChannels = 2; + hEncoder->config.numSideChannels = 0; + hEncoder->config.numBackChannels = 0; + hEncoder->config.numLFEChannels = 0; + break; + case 1: + hEncoder->config.numFrontChannels = 1; + hEncoder->config.numSideChannels = 0; + hEncoder->config.numBackChannels = 0; + hEncoder->config.numLFEChannels = 0; + break; + } + } + assert((hEncoder->config.outputFormat == 0) || (hEncoder->config.outputFormat == 1)); switch( hEncoder->config.inputFormat ) @@ -306,6 +402,12 @@ *maxOutputBytes += 1; /* for CRC */ #endif + if (!numChannels || numChannels > 64) { + fprintf(stderr, "faacEncOpen: invalid number of channels %u\n", + numChannels); + return NULL; + } + hEncoder = (faacEncStruct*)AllocMemory(sizeof(faacEncStruct)); SetMemory(hEncoder, 0, sizeof(faacEncStruct)); @@ -324,7 +426,6 @@ hEncoder->config.mpegVersion = MPEG4; hEncoder->config.aacObjectType = LTP; hEncoder->config.allowMidside = 1; - hEncoder->config.useLfe = 1; hEncoder->config.useTns = 0; hEncoder->config.bitRate = 0; /* default bitrate / channel */ hEncoder->config.bandWidth = bwfac * hEncoder->sampleRate; @@ -340,6 +441,91 @@ /* default channel map is straight-through */ for( channel = 0; channel < 64; channel++ ) hEncoder->config.channel_map[channel] = channel; + + /* Define a sensible default channel configuration */ + if (numChannels <= 6 || numChannels == 8) { + switch (numChannels) { + case 8: + hEncoder->config.channelConfiguration = 7; + hEncoder->config.numFrontChannels = 5; + hEncoder->config.numSideChannels = 0; + hEncoder->config.numBackChannels = 2; + hEncoder->config.numLFEChannels = 1; + break; + case 6: + hEncoder->config.channelConfiguration = 6; + hEncoder->config.numFrontChannels = 3; + hEncoder->config.numSideChannels = 0; + hEncoder->config.numBackChannels = 2; + hEncoder->config.numLFEChannels = 1; + break; + case 5: + hEncoder->config.channelConfiguration = 5; + hEncoder->config.numFrontChannels = 3; + hEncoder->config.numSideChannels = 0; + hEncoder->config.numBackChannels = 2; + hEncoder->config.numLFEChannels = 0; + break; + case 4: + hEncoder->config.channelConfiguration = 4; + hEncoder->config.numFrontChannels = 3; + hEncoder->config.numSideChannels = 0; + hEncoder->config.numBackChannels = 1; + hEncoder->config.numLFEChannels = 0; + break; + case 3: + hEncoder->config.channelConfiguration = 3; + hEncoder->config.numFrontChannels = 3; + hEncoder->config.numSideChannels = 0; + hEncoder->config.numBackChannels = 0; + hEncoder->config.numLFEChannels = 0; + break; + case 2: + hEncoder->config.channelConfiguration = 2; + hEncoder->config.numFrontChannels = 2; + hEncoder->config.numSideChannels = 0; + hEncoder->config.numBackChannels = 0; + hEncoder->config.numLFEChannels = 0; + break; + case 1: + hEncoder->config.channelConfiguration = 1; + hEncoder->config.numFrontChannels = 1; + hEncoder->config.numSideChannels = 0; + hEncoder->config.numBackChannels = 0; + hEncoder->config.numLFEChannels = 0; + break; + } + } else { + hEncoder->config.channelConfiguration = 0; + hEncoder->config.numFrontChannels = 0; + hEncoder->config.numSideChannels = 0; + hEncoder->config.numBackChannels = 0; + hEncoder->config.numLFEChannels = 0; + for (channel = numChannels; channel > 0; channel--) { + // 7 channels: 7.0 (C L R Ls Rs Rls Rrs) + // 9 channels: 9.0 (Lc Rc L R Ls Rs Rls Rrs Cs) + // 10 channels: 10.0 (C Lc Rc L R Ls Rs Rls Rrs Cs) + // for more than 10 channels, use faacEncSetConfiguration() + if (hEncoder->config.numFrontChannels < 3) { + // C, L, R + hEncoder->config.numFrontChannels++; + } else if (hEncoder->config.numBackChannels < 2) { + // Ls or Rls, Rs or Rrs + hEncoder->config.numBackChannels++; + } else if (hEncoder->config.numSideChannels < 2) { + // Ls, Rs + hEncoder->config.numSideChannels++; + } else if (hEncoder->config.numBackChannels < 3) { + // Cs + hEncoder->config.numBackChannels++; + } else if (hEncoder->config.numFrontChannels < 5) { + // Lc, Rc + hEncoder->config.numFrontChannels++; + } else { + break; + } + } + } /* by default we have to be compatible with all previous software @@ -459,14 +645,13 @@ double fix; #endif - /* local copy's of parameters */ + /* local copies of parameters */ ChannelInfo *channelInfo = hEncoder->channelInfo; CoderInfo *coderInfo = hEncoder->coderInfo; unsigned int numChannels = hEncoder->numChannels; unsigned int sampleRate = hEncoder->sampleRate; unsigned int aacObjectType = hEncoder->config.aacObjectType; unsigned int mpegVersion = hEncoder->config.mpegVersion; - unsigned int useLfe = hEncoder->config.useLfe; unsigned int useTns = hEncoder->config.useTns; unsigned int allowMidside = hEncoder->config.allowMidside; unsigned int bandWidth = hEncoder->config.bandWidth; @@ -484,7 +669,11 @@ return 0; /* Determine the channel configuration */ - GetChannelInfo(channelInfo, numChannels, useLfe); + GetChannelInfo(channelInfo, + hEncoder->config.numFrontChannels, + hEncoder->config.numSideChannels, + hEncoder->config.numBackChannels, + hEncoder->config.numLFEChannels); /* Update current sample buffers */ for (channel = 0; channel < numChannels; channel++)