shithub: aacenc

ref: 60fa9e81165a47bf492e0835459e2dedf72df660
dir: /libfaac/joint.c/

View raw version
/*
 * FAAC - Freeware Advanced Audio Coder
 * Copyright (C) 2001 Menno 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
 *
 * $Id: joint.c,v 1.4 2001/03/06 14:01:36 menno Exp $
 */

#include "channels.h"
#include "util.h"

void MSEncode(CoderInfo *coderInfo,
			  ChannelInfo *channelInfo,
			  double *spectrum[MAX_CHANNELS],
			  unsigned int numberOfChannels,
			  unsigned int msenable)
{
	unsigned int chanNum;
	int sfbNum;
	int lineNum;
	double sum,diff;

	/* Look for channel_pair_elements */
	for (chanNum=0;chanNum<numberOfChannels;chanNum++) {
		if (channelInfo[chanNum].present) {
			if ((channelInfo[chanNum].cpe)&&(channelInfo[chanNum].ch_is_left)) {
				int leftChan=chanNum;
				int rightChan = channelInfo[chanNum].paired_ch;
				channelInfo[leftChan].msInfo.is_present = 0;
				channelInfo[rightChan].msInfo.is_present = 0;

				/* Perform MS if block_types are the same */
				if ((coderInfo[leftChan].block_type==coderInfo[rightChan].block_type)&&(msenable)) { 
					int numGroups;
					int maxSfb;
					int g,w,line_offset;
					int startWindow,stopWindow;
					MSInfo *msInfoL;
					MSInfo *msInfoR;

					channelInfo[leftChan].common_window = 1;  /* Use common window */
					channelInfo[leftChan].msInfo.is_present = 1;
					channelInfo[rightChan].msInfo.is_present = 1;

					numGroups = coderInfo[leftChan].num_window_groups;
					maxSfb = coderInfo[leftChan].max_sfb;
					w=0;

					/* Determine which bands should be enabled */
					msInfoL = &(channelInfo[leftChan].msInfo);
					msInfoR = &(channelInfo[rightChan].msInfo);
					
					/* Perform sum and differencing on bands in which ms_used flag */
					/* has been set. */
					if (coderInfo[leftChan].block_type == ONLY_SHORT_WINDOW) {
						line_offset=0;
						startWindow = 0;
						for (g=0;g<numGroups;g++) {
							int numWindows = coderInfo[leftChan].window_group_length[g];
							stopWindow = startWindow + numWindows;
							for (sfbNum=0;sfbNum<maxSfb;sfbNum++) {
								/* Enable MS mask */
								int use_ms = 1;
								for (w=startWindow;w<stopWindow;w++) {
									use_ms = min(use_ms, msInfoL->ms_usedS[w][sfbNum]);
								}
								msInfoL->ms_used[g*maxSfb+sfbNum] = use_ms; /* write this to bitstream */
								msInfoR->ms_used[g*maxSfb+sfbNum] = use_ms;
								for (w=startWindow;w<stopWindow;w++) {
									msInfoL->ms_usedS[w][sfbNum] = use_ms;
									msInfoR->ms_usedS[w][sfbNum] = use_ms;
								}
								for (w=startWindow;w<stopWindow;w++) {
									if (msInfoL->ms_usedS[w][sfbNum]) {
										for (lineNum = coderInfo[leftChan].sfb_offset[sfbNum];
											 lineNum < coderInfo[leftChan].sfb_offset[sfbNum+1];
											 lineNum++)
										{
											line_offset = w*BLOCK_LEN_SHORT;
											sum=spectrum[leftChan][line_offset+lineNum]+spectrum[rightChan][line_offset+lineNum];
											diff=spectrum[leftChan][line_offset+lineNum]-spectrum[rightChan][line_offset+lineNum];
											spectrum[leftChan][line_offset+lineNum] = 0.5 * sum;
											spectrum[rightChan][line_offset+lineNum] = 0.5 * diff;
										}
									}
								}
							}
							startWindow = stopWindow;
						}
					} else {
						for (sfbNum = 0;sfbNum < maxSfb; sfbNum++) {
							msInfoR->ms_used[sfbNum] = msInfoL->ms_used[sfbNum];

							/* Enable MS mask */
							if (msInfoL->ms_used[sfbNum]) {
								for (lineNum = coderInfo[leftChan].sfb_offset[sfbNum];
									 lineNum < coderInfo[leftChan].sfb_offset[sfbNum+1];
									 lineNum++)
								{
									sum=spectrum[leftChan][lineNum]+spectrum[rightChan][lineNum];
									diff=spectrum[leftChan][lineNum]-spectrum[rightChan][lineNum];
									spectrum[leftChan][lineNum] = 0.5 * sum;
									spectrum[rightChan][lineNum] = 0.5 * diff;
								}
							}
						}
					}
				}
			}
		}
	}
}

void MSReconstruct(CoderInfo *coderInfo,
				   ChannelInfo *channelInfo,
				   int numberOfChannels)
{
	int chanNum;
	int sfbNum;
	int lineNum;
	double sum,diff;

	/* Look for channel_pair_elements */
	for (chanNum=0;chanNum<numberOfChannels;chanNum++) {
		if (channelInfo[chanNum].present) {
			if ((channelInfo[chanNum].cpe)&&(channelInfo[chanNum].ch_is_left)) {
				int leftChan=chanNum;
				int rightChan=channelInfo[chanNum].paired_ch;

				MSInfo *msInfoL;
				msInfoL = &(channelInfo[leftChan].msInfo);
				if (msInfoL->is_present) {
					int numGroups = coderInfo[leftChan].num_window_groups;
					int maxSfb = coderInfo[leftChan].max_sfb;
					int w,line_offset;
					int startWindow;
					w=0;

					line_offset=0;
					startWindow = 0;
					if (coderInfo[leftChan].block_type != ONLY_SHORT_WINDOW) {
						for (sfbNum = 0;sfbNum < maxSfb; sfbNum++) {

							if (msInfoL->ms_used[sfbNum]) {
								for (lineNum = coderInfo[leftChan].sfb_offset[sfbNum];
									 lineNum < coderInfo[leftChan].sfb_offset[sfbNum+1];
									 lineNum++)
								{
									sum=coderInfo[leftChan].requantFreq[lineNum];
									diff=coderInfo[rightChan].requantFreq[lineNum];
									coderInfo[leftChan].requantFreq[lineNum] = (sum+diff);
									coderInfo[rightChan].requantFreq[lineNum] = (sum-diff);
								}
							}
						}
					}
				}
			}
		}
	}
}