// file: $isip/class/algo/Generator/gen_04.cc
// version: $Id: gen_04.cc 10391 2006-01-25 03:32:38Z prasad $
//

// isip include files
//
#include "Generator.h"

// method: sofSize
//
// arguments: none
//
// return: size of object
//
// this method return the size of the object in the Sof file and is
// used for binary write
//
long Generator::sofSize() const {

  // start with enough space for the algorithm
  //
  long bytes = 0;

  // add the size of the signal algorithm
  //
  bytes += ALGO_MAP.elementSofSize();
  
  // add the space required for the mode name
  //
  bytes += DMODE_MAP.elementSofSize();  
 
  // add the space required for the  implementation name
  //
  bytes += IMPL_MAP.elementSofSize();
 
  // add number of channels of the signal
  //
  bytes += channels_d.sofSize();  

  // add the space required for the debug level
  //
  bytes += debug_level_d.sofSize();

  // add the space required for random seed
  //
  bytes += seed_d.sofSize();

  // add the space required for gen sample frequency
  //
  bytes += gen_sample_freq_d.sofSize();  
  
  // add the size of the frequency, amplitude, phase and bias of the signal
  // if the signal is a sine, triangle, square wave or a pulse train
  //
  if ((algorithm_d == SINE) || (algorithm_d == PULSE) ||
      (algorithm_d == TRIANGLE) || (algorithm_d == SQUARE)) {
    bytes += frequency_d.sofSize();
    bytes += amplitude_d.sofSize(); 
    bytes += PHMODE_MAP.elementSofSize();
    bytes += phase_d.sofSize();
    bytes += bias_d.sofSize();
  }

  // add the size of the duty cycle if the signal is a
  //  pulse train. triangle, square
  //
  if ((algorithm_d == PULSE) || (algorithm_d == TRIANGLE) ||
      (algorithm_d == SQUARE)) {
    bytes += duty_cycle_d.sofSize();
  }

  // add the size of the mean and variance if the signal
  //  is a guassian noise
  //
  if (algorithm_d == GAUSSIAN) {
    bytes += mean_d.sofSize();
    bytes += variance_d.sofSize();
  }

  // add the size of the phase of the signal
  //
  
  // return the size
  //
  return bytes;
  
}

// method: write
//
// arguments:
//  Sof& sof: (input) sof file object
//  long tag: (input) sof object instance tag
//  const String& name: (input) sof object instance name
//
// return: a boolean indicating status
//
// this method has the object write itself to an Sof file
//
boolean Generator::write(Sof& sof_a, long tag_a, const String& name_a) const {
  
  long obj_size = 0;

  if (sof_a.isText()) {
    obj_size = Sof::ANY_SIZE;
  }
  else {
    obj_size = sofSize();
  }
  
  // put the object into the sof file's index
  //
  if (!sof_a.put(name_a, tag_a, obj_size)) {
    return false;
  }

  // exit gracefully
  //
  return writeData(sof_a);
}

// method: writeData
//
// arguments:
//  Sof& sof: (input) sof file object
//  const String& pname: (input) parameter name
//
// return: logical error status
//
// this method has the object writes itself from an Sof file. it assumes
// that the Sof file is already positioned correctly.
//
boolean Generator::writeData(Sof& sof_a, const String& pname_a) const {

  // write a start string if necessary
  //
  sof_a.writeLabelPrefix(pname_a);
  
  // write the algorithm of the signal
  //
  ALGO_MAP.writeElementData(sof_a, PARAM_ALGORITHM, (long)algorithm_d);
  
  // write the implementation type
  //
  IMPL_MAP.writeElementData(sof_a, PARAM_IMPLEMENTATION,
			    (long)implementation_d);
  
  // write number of channels of the signal
  // 
  channels_d.writeData(sof_a, PARAM_CHANNELS);
  
  // write random seed of the signal
  //
  seed_d.writeData(sof_a, PARAM_SEED);
  
  // write the gen sample frequency
  //
  gen_sample_freq_d.writeData(sof_a, PARAM_GEN_SAMPLE_FREQUENCY);  

  // write general data
  //
  debug_level_d.writeData(sof_a, PARAM_DBGL);

  // check known algorithms: invoke the proper lower-level method
  //  currently, all algorithms use the same i/o methods
  //
  if ((algorithm_d == SINE) ||
      (algorithm_d == SQUARE) ||
      (algorithm_d == TRIANGLE) ||
      (algorithm_d == PULSE) ||
      (algorithm_d == GAUSSIAN) ||
      (algorithm_d == LORENTZ) ||
      (algorithm_d == ROSSLER)) {
    return writeDataCommon(sof_a, pname_a);
  }

  // check unknown algorithms
  //
  else {
    return Error::handle(name(), L"writeData",
			 ERR_UNKALG, __FILE__, __LINE__);
  }

  // put an end string if necessary
  //
  sof_a.writeLabelSuffix(pname_a);
  
  // exit gracefully
  //
  return true;
}

// method: writeDataCommon
//
// arguments:
//  Sof& sof: (input) sof file object
//  const String& pname: (input) parameter name
//
// return: a boolean value indicating status
//
// this method writes data to a file for several algorithms that
// share the same parameters
//
boolean Generator::writeDataCommon(Sof& sof_a,
				   const String& pname_a) const {
  
  // write the frequency, amplitude and phase if the signal is of algorithm
  //  sine or pulse or triangle
  //
  if ((algorithm_d == SINE) || (algorithm_d == PULSE) ||
      (algorithm_d == TRIANGLE) || (algorithm_d == SQUARE)) {
    frequency_d.writeData(sof_a, PARAM_FREQUENCY);
    amplitude_d.writeData(sof_a, PARAM_AMPLITUDE);
    phase_d.writeData(sof_a, PARAM_PHASE);
    bias_d.writeData(sof_a, PARAM_BIAS);
    PHMODE_MAP.writeElementData(sof_a, PARAM_PHMODE, (long)phmode_d);
  }
  
  // write the duty cycle if the signal is of
  //  algorithm triangle or pulse
  //
  if ((algorithm_d == PULSE) || (algorithm_d == TRIANGLE) ||
      (algorithm_d == SQUARE)) {
    duty_cycle_d.writeData(sof_a, PARAM_DUTY_CYCLE);
  }
  
  // write the mean and variance if the signal is of algorithm
  // gaussian
  //
  if (algorithm_d == GAUSSIAN) {
    mean_d.writeData(sof_a, PARAM_MEAN);
    variance_d.writeData(sof_a, PARAM_VARIANCE);
  }

  // write the mean and variance if the signal is of algorithm
  // Lorentz or Rossler
  //
  if ((algorithm_d == LORENTZ) || (algorithm_d == ROSSLER)) {
    chaos_a_d.writeData(sof_a, PARAM_CHAOS_A);
    chaos_a_d.writeData(sof_a, PARAM_CHAOS_B);
    chaos_a_d.writeData(sof_a, PARAM_CHAOS_C);
    chaos_x0_d.writeData(sof_a, PARAM_CHAOS_X0);
    chaos_y0_d.writeData(sof_a, PARAM_CHAOS_Y0);
    chaos_z0_d.writeData(sof_a, PARAM_CHAOS_Z0);
    chaos_integrate_upsample_d.writeData(sof_a, PARAM_CHAOS_INTEGRATE_UPSAMPLE);    
  }

  // exit gracefully
  //
  return true;
}
