/*  dskchnhd.C   */
/*  Copyright 1990 Mountain Math Software  */
/*  All Rights Reserved                    */

#include "tarnod.h"
#include "dskchnhd.h"
#include "timing.h"
#include "strmstr.h"
#include "newaloc.h"
#include "cgidbg.h"

#define SET(Param) Param = C30.Param
#define SET_T(Param) Param = (TimingType) C30.Param

NodeOutChannelHeader::NodeOutChannelHeader(C30NodeOutChannelHeader& C30)
{
		SET(NumeratorSampling);
		SET(DenominatorSampling);
		SET_FLOAT(SampleRate);
		SET_T(TheTimingType);
		SET_FLOAT(FirstSample);
		SET_FLOAT(ErrorTolerance);
		SET_FLOAT(DeltaTimeBase);
		SET(ElementSize);
		SET(BlockSize);
		SET_FLOAT(MinimumX);
		SET_FLOAT(MaximumX);
		SET_FLOAT(SampleRateFactor);
}
#undef SET
#undef SET_T
#undef SET_FLOAT


#ifdef TI_C30
// uint32 SetFloatTemp ;
#endif 

#ifndef NO_USR_MSGS
void NodeOutChannelHeader::CheckTiming(int16 Flags)
{
	if (Flags & 4) {
		// LogOut << "CheckTiming(" << Flags << ")\n" ;
		SampleRateFactor = 1. ;
		NumeratorSampling = DenominatorSampling = 1 ;
		FirstSample = 0.0 ;
	}
	int Warn = 0 ;
	if (SampleRateFactor < 1.e-50) {
		Warn |= 1 ;
		SampleRateFactor = 1 ;
	}
	if (NumeratorSampling < 1.e-50) {
		NumeratorSampling = 1 ;
		Warn |= 2 ;
	}
	if (DenominatorSampling < 1.e-50) {
		DenominatorSampling = 1 ;
		Warn |= 4 ;
	}
	if (SampleRate < 1.e-50) Warn |= 8 ;
	if (Warn > 1) SampleRate = ((double) NumeratorSampling) /
		DenominatorSampling ;
	// if (Warn) LogOut << "Bad timing header, Warn = " << Warn << "\n" ;
}
#endif

#ifdef INTERACTIVE
NodeOutChannelHeader::NodeOutChannelHeader(const TimingDescription& TheTiming,
	const StreamStr& TheStream)
{

#define GET(A) A = TheTiming.A
	GET(NumeratorSampling) ;
	GET(DenominatorSampling) ;
	GET(SampleRate) ;
	GET(TheTimingType) ;
	GET(FirstSample) ;
	GET(ErrorTolerance) ;
	GET(DeltaTimeBase) ;
#undef GET

	ElementSize = TheStream.GetElementSize() ;
	BlockSize = TheStream.GetBlockSize() ;
	MinimumX = TheStream.GetMinimumX() ;
	MaximumX = TheStream.GetMaximumX() ;
	SampleRateFactor = TheStream.GetSampleRateFactor() ;

}
#else
NodeOutChannelHeader::NodeOutChannelHeader(class TargetNode& TheNode,
	int Channel)
{
	ElementSize = TheNode.GetInEltSize(Channel) ;
	BlockSize = TheNode.GetBlockSize(Channel) ;
	NumeratorSampling = 1 ;
	DenominatorSampling = TheNode.GetIncrementIn(Channel);
	SampleRate = 1. / DenominatorSampling ;
	TheTimingType=  TimingTypeLinear;
	FirstSample = 0.0 ;
	ErrorTolerance = 0.0 ;
	DeltaTimeBase = 0.0 ;

	MinimumX = 0 ;
	MaximumX = 0 ;
	SampleRateFactor = 1 ;
}
#endif

NodeOutChannelHeader::NodeOutChannelHeader()
{
	Clear() ;
}

void NodeOutChannelHeader::SetFromImage(const char * Image)
{
	MoveNBytes((char *) this, Image, sizeof(*this));
} 

void NodeOutChannelHeader::Clear()
{
	NumeratorSampling = 0 ;
	DenominatorSampling = 0 ;
	FirstSample = 0 ;
	ElementSize = 0 ;
}

double NodeOutChannelHeader::GetTimeFirst()
{
	return FirstSample;
}

void NodeOutChannelHeader::Display(OutputType Where)
{
#ifdef INTERACTIVE
	*Output + Where <<
		"The relative sample rate from the generating process was " <<
		NumeratorSampling << "/" << DenominatorSampling << ".\n" ;
	// *Output << "This sample rate is ignored in computing the new network"
	// 	<< " sample rates.\n" ;
	*Output << "The absolute sample rate is " << SampleRate << "\n" ;
	*Output << "This "  << (TheTimingType == TimingTypeLinear?
		"is" : "is not") << " a linearly sampled data stream.\n";
	if (BlockSize>ElementSize) {
		*Output <<
			"This is a two dimensional data stream of block size "
			<< BlockSize << "\n" ;
		if (SampleRateFactor > 0.0) {
			*Output << "The axis of the second dimension is hz.\n";
			*Output << "The labeling of this axis is:\n" ;
			*Output << SampleRateFactor * SampleRate <<
				" hz. per frequency axis sample.\n";
		}
		*Output << "The axis ranges from " <<
			MinimumX * SampleRate << " to " <<
			MaximumX * SampleRate << ".\n" ;
		
	} else {
		if (MinimumX) *Output << "MinimumX = " << MinimumX << "\n" ;
		if (MaximumX) *Output << "MaximumX = " << MaximumX << "\n" ;
	}
	*Output << "SampleRateFactor = " << SampleRateFactor << "\n" ;
	if (ElementSize == 2) *Output << "The data is complex, i. e." <<
		" it has two multiplexed elements in each sample.\n" ;
	if (ElementSize > 2) *Output << "Each sample contains " <<
		ElementSize << " multiplexed elements.\n" ;
	*Output << "The first sample time is " << FirstSample << ".\n" ;
/*
 *	if (!NumberWords) *Output<< "There are no words ";
 *	else if (NumberWords == 1)
 *		*Output << "There is 1 word" ;
 *	else *Output << "There are " << NumberWords << " words" ;
 *	if (ElementSize && NumberWords)
 *			*Output << " (" << NumberWords/ElementSize <<
 *		" samples) " ;
 *	*Output << "in this channel.\n" ;
 */
#endif
}

void NodeOutChannelHeader::Dump(ostream& Out)
{
#ifdef INTERACTIVE
	Out << "Sample rate = " << NumeratorSampling << " / " <<
		DenominatorSampling << ".\n" ;
	Out << "( 0x" << NumeratorSampling << " / 0x" << DenominatorSampling 
		<< " )\n" ;
	int32 * DumpDoubleAsHex = (int32 *) &FirstSample ;
	char buf1[32];
	char buf2[32];
	sprintf(buf1,"%0x",DumpDoubleAsHex[0]);
	sprintf(buf2,"%0x",DumpDoubleAsHex[1]);
	Out << "Time of first sample = " << FirstSample << " ( 0x" <<
		buf1 << ", 0x" <<
		buf2 << " )\n" ;
	sprintf(buf1,"%0x",ElementSize);
	Out << "ElementSize = " << ElementSize << "( 0x" << buf1
		<< ")\n" ;
/*
 *	Out << "NumberWords = " << NumberWords << "( 0x" <<
 *		hex(NumberWords) << ")\n" ;
 */
#endif
}
		
#ifdef INTERACTIVE
TimingDescription TempTiming ;

TimingDescription * NodeOutChannelHeader::GetInitTiming()
{
/*
 *	for (;;) {
 *		if (NumeratorSampling > 0)
 *			if (DenominatorSampling > 0)
 *				if (SampleRate > 1.e-50) break ;
 *		LogOut <<
 *	"NodeOutChannelHeader::GetInitTiming: Channel Header sampling bad.\n" ;
 *		NumeratorSampling = 1 ;
 *		DenominatorSampling = 1 ;
 *		SampleRate = 1. ;
 *		break ;
 *	}
 */
	TempTiming.Clear();
	TempTiming.NumeratorSampling = NumeratorSampling ;
	TempTiming.DenominatorSampling = DenominatorSampling ;
	TempTiming.FirstSample = FirstSample ;
	return &TempTiming ;
}
#endif
double NodeOutChannelHeader::GetTimingRatio()
{
	return ((double) NumeratorSampling) /
		((double) DenominatorSampling) ;
}

