/*
 *  intrpolc.C from ObjectProDSP 0.1
 *  Copyright (C) 1994, Mountain Math Software. All rights reserved.
 *  
 *  This file is part of ObjectProDSP, a tool for Digital Signal
 *  Processing design, development and implementation. It is free
 *  software provided you use and distribute it under the terms of
 *  version 2 of the GNU General Public License as published
 *  by the Free Software Foundation. You may NOT distribute it or
 *  works derived from it or code that it generates under ANY
 *  OTHER terms.  In particular NONE of the ObjectProDSP system is
 *  licensed for use under the GNU General Public LIBRARY License.
 *  Mountain Math Software plans to offer a commercial version of
 *  ObjectProDSP for a fee. That version will allow redistribution
 *  of generated code under standard commercial terms.
 *  
 *  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 version 2 of the GNU General
 *  Public License along with this program. See file COPYING. If not
 *  or if you wish information on commercial versions and licensing
 *  write Mountain Math Software, P. O. Box 2124, Saratoga, CA 95070,
 *  USA, or send us e-mail at: support@mtnmath.com.
 *  
 *  You may also obtain the GNU General Public License by writing the
 *  Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139,
 *  USA.  However if you received a copy of this program without the
 *  file COPYING or without a copyright notice attached to all text
 *  files, libraries and executables please inform Mountain Math Software.
 *  
 *  ObjectProDSP is a trademark of Mountain Math Software.
 */
#include "ObjProUsr/intrpol.h"
#include "ObjProGen/newaloc.h"
#include "ObjProComGui/cgidbg.h"

void Interpolate::ctor()
{
	ElementSize = 0 ;
    LastInputSample = 0 ;
    NextInputSample = 0 ;
    InputDivOutput = ((double) GetDeltaIn()) / GetDeltaOut() ;
    OutputIndex = 0 ;
    InputHighIndex = -1 ;
	input_sample_index = 0 ;
	output_sample_index = 0 ;
}

void Interpolate::dtor()
{
	delete LastInputSample ;
	delete NextInputSample ;
}

int Interpolate::UpdateInput(int Needed)
{
	int DidInput = 0 ;
	while (InputHighIndex < Needed) {
		for (int i = 0 ; i < ElementSize; i++)  {
			LastInputSample[i] = NextInputSample[i];	
			NextInputSample[i] = ReadWord();
		}
/*
 *		LogOut << "Read i = " << input_sample_index << ", o = " <<
 *			output_sample_index << "\n" ;
 */
		input_sample_index++ ;
		InputHighIndex++ ;
		DidInput++ ;
	}
	return DidInput ;
}

ErrCode Interpolate::kernel(int32 k)
{
	if (!LastInputSample) {
		ElementSize = GetEltSize();
		LastInputSample = NEW(MachWord,ElementSize);
		NextInputSample = NEW(MachWord,ElementSize);
		for (int i = 0 ; i < ElementSize; i++)
			NextInputSample[i] = 0 ;
	}
	for (int l = 0 ; l < k ; l++) 
	 for (int c = 0 ; c < GetDeltaOut(); c++)
	  for (int b = 0 ; b < GetBlockSize(); b++) {
			double InputPosition = InputDivOutput * OutputIndex ;
			int InputLow = (int) InputPosition ;
			double HighDiff = InputPosition - InputLow ;
/*
 *	 	 	LogOut << "InputHighIndex = " << InputHighIndex
 *				<< ", OutputIndex = " << OutputIndex << "\n" ;
 */
			if (HighDiff < 1.e-3) {
				UpdateInput(InputLow);
				for (int i=0; i < ElementSize;i++) {
					WriteWord(NextInputSample[i]);
				}
/*
 *				LogOut << "Write i = " << input_sample_index << ", o = " <<
 *					output_sample_index << "\n" ;
 */
				output_sample_index++ ;
				OutputIndex++ ;
				continue ;
			}
			UpdateInput(InputLow+1) ;
			for (int i=0; i < ElementSize;i++) {
				double LowDiff = 1.0 - HighDiff ;
				MachWord Low = (MachWordCast) (LowDiff *
					((double) LastInputSample[i])) ;
				MachWord High = (MachWordCast)  (HighDiff *
					((double) NextInputSample[i]));
				WriteWord((MachWordCast) Low + (MachWordCast) High) ;
/*
 *				LogOut << "write "
 *					<< ((MachWordCast) Low + (MachWordCast) High) << "\n" ;
 *
 *				LogOut << "Low = " << (MachWordCast)  Low << ", High = "
 *					<< (MachWordCast) High << "\n" ;
 *				LogOut << "LowDiff = " << LowDiff << ", HighDiff = "
 *					<< HighDiff << "\n" ;
 *				LogOut << "Next = " << (MachWordCast) NextInputSample[i] << 
 *					", Last = " << (MachWordCast) LastInputSample[i] << "\n" ;
 */
 			}
/*
 *			LogOut << "Write i = " << input_sample_index << ", o = " <<
 *				output_sample_index << "\n" ;
 */
			output_sample_index++ ;
			OutputIndex++;
	}
	return OK ;
}
