/*
 *  rlfirk.C from ObjectProDSP
 *  Copyright (C) 1994, Mountain Math Software, All rights reserved.
 *  Licensed for free use and distribution under version 2 of the Gnu General
 *  Public License. Please see file COPYING for details and restrictions.
 *  
 *  ObjectProDSP is a trademark of Mountain Math Software.
 */
#include <stream.h>
#include "rlfirk.h"
#include "newaloc.h"
#include "tmparth.h"
#include "hrdcmp.h"
#include "dfnode.h"
#include "cgidbg.h"

RealFilter::RealFilter(int length, int resample, int zero_pad,
	MachWord * coeff, TargetNode * network_intfc)
{
	FilterLength = length;
	Resample = resample ;
	ZeroPad = zero_pad ;
	Coeff = coeff ;
	NetworkIntfc = network_intfc ;
	CoeffLength = FilterLength >> 1 ;
	Odd = FilterLength & 1 ;
	DataBufSize = FilterLength  ;
	DataBuf = NEW(MachWord,DataBufSize);
	Reset();
}

void RealFilter::Reset()
{
	NextSampleToWrite = 0;
	ValidData = 0;
	ZeroPadIndex = 0 ;
	for (int i = 0 ; i < DataBufSize;i++) DataBuf[i] = 0 ;
}

RealFilter::~RealFilter()
{
	delete DataBuf ;
	DataBuf = 0;
}

ErrCode RealFilter::ExecuteKernel(int k)
{
	// LogOut << "RealFilter::ExecuteKernel(" << k << ")\n";
	for (int i = 0 ; i < k ; i++) {
		while (ValidData < DataBufSize) {
			MachWord Data ;
			if (ZeroPadIndex) Data = 0 ;
			else Data = NetworkIntfc->ReadWord() ;
			if (ZeroPad) if(++ZeroPadIndex > ZeroPad)
				ZeroPadIndex=0;
			DataBuf[NextSampleToWrite++] = Data ;
			ValidData++ ;
			if (NextSampleToWrite >= DataBufSize)
				NextSampleToWrite = 0;
		}
		int32 CoeffIndex = 0 ;
		AccMachWord Sum = 0 ;
		int UpFlag = 1;

		for (int32 j = 0 ; j < FilterLength; j++ ) {
			int32 jj = j + NextSampleToWrite ;
			if (jj >= DataBufSize) jj -= DataBufSize ;

			if (DataBuf[jj].val()) {
				MachWord Tmp = Coeff[CoeffIndex] ;
				Sum+= ((AccMachWord) DataBuf[jj]) * (AccMachWord) Tmp;
			}
			if (UpFlag) CoeffIndex++ ;
			else CoeffIndex-- ;
			if (CoeffIndex >= CoeffLength) {
				if (Odd) CoeffIndex-=2 ;
				else CoeffIndex-- ;
				UpFlag = 0;
			}
		}
		MachWord Out = AccScale(Sum,0);
		// LogOut << "Filter out = " << Sum.val() << ", " << Out.val() << "\n" ;
		ValidData -= Resample;
		NetworkIntfc->WriteWord(Out);
	}
	return OK ;
}

